Commit 62cf4308dc566da5a6fd7cbafc564eb1109827a4
Merge branch 'local_dev_ft' into 'main_dev'
perf: 优化重构app完成,优化主分包体积大小,主包不超过1.5M See merge request yunteng/thingskit-app!121
Showing
101 changed files
with
6367 additions
and
6311 deletions
| 1 | 1 | <script> |
| 2 | 2 | import store from '@/store'; |
| 3 | - // import { | |
| 4 | - // scene | |
| 5 | - // } from '@/config/common'; | |
| 6 | 3 | |
| 7 | 4 | export default { |
| 8 | 5 | //设置全局变量,解绑时从这里取 |
| ... | ... | @@ -10,27 +7,12 @@ |
| 10 | 7 | openId: '' |
| 11 | 8 | }, |
| 12 | 9 | onLaunch(e) { |
| 13 | - //取出缓存数据 | |
| 14 | - // store.commit('setCacheData'); | |
| 15 | - //获取二维码信息 | |
| 16 | - // scene(e); | |
| 17 | 10 | // #ifdef APP-PLUS |
| 18 | 11 | uni.reLaunch({ |
| 19 | 12 | url: '/pages/index/splash' |
| 20 | 13 | }) |
| 21 | 14 | // #endif |
| 22 | 15 | }, |
| 23 | - onShow(e) { | |
| 24 | - // #ifdef MP | |
| 25 | - // mpUpData(); //检测小程序更新 | |
| 26 | - // #endif | |
| 27 | - // #ifdef APP-PLUS | |
| 28 | - // uni.reLaunch({ | |
| 29 | - // url: '/pages/index/splash' | |
| 30 | - // }) | |
| 31 | - // #endif | |
| 32 | - }, | |
| 33 | - onHide() {}, | |
| 34 | 16 | onUnload(){ |
| 35 | 17 | uni.setStorageSync('getConfiguration', { |
| 36 | 18 | isConfiguration: false | ... | ... |
| 1 | +<template> | |
| 2 | + <view class="alarm-detail-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view class="alarm-detail-column"> | |
| 6 | + <view class="u-flex detail-column"> | |
| 7 | + <view class="column-line" v-for="(item,index) in alarmDetail" :key="index"> | |
| 8 | + <view class="column"> | |
| 9 | + <text class="text-org-bold">{{item.label}}</text> | |
| 10 | + <text class="text-device-muted text-clip alarm-text" | |
| 11 | + :style="{color:hasColor.includes(item.label)?'#DE4437':''}"> | |
| 12 | + {{item.label===hasColor[0]? setAlarmStatus(item.value):item.label===hasColor[1]?setAlarmSeverity(item.value): | |
| 13 | + item.label==='告警值:'?formatAlarmValueText:item.label==='告警条件:'?formatAlarmConditionText | |
| 14 | + :item.label==='告警设备:'?formatDeviceText:item.value}} | |
| 15 | + </text> | |
| 16 | + </view> | |
| 17 | + <view class="bottom-line"></view> | |
| 18 | + </view> | |
| 19 | + </view> | |
| 20 | + </view> | |
| 21 | + <!-- #ifdef MP --> | |
| 22 | + <view class="handle-result text-org-bold" style="">处理结果</view> | |
| 23 | + <view class="hanle-main"> | |
| 24 | + <u--form :label-style="{ 'font-size': '0rpx' }" style="padding-left: 26rpx;" labelPosition="left" | |
| 25 | + :model="formModel" ref="form1"> | |
| 26 | + <u-form-item label="." prop="result" ref="item3"> | |
| 27 | + <view style="position: relative;left: -60rpx;"> | |
| 28 | + <u--textarea border="none" height="96" placeholder="请输入处理结果" v-model="formModel.result" count> | |
| 29 | + </u--textarea> | |
| 30 | + </view> | |
| 31 | + </u-form-item> | |
| 32 | + </u--form> | |
| 33 | + </view> | |
| 34 | + <!-- #endif --> | |
| 35 | + <!-- #ifdef APP-PLUS --> | |
| 36 | + <view class="handle-result text-org-bold">处理结果</view> | |
| 37 | + <view class="hanle-main"> | |
| 38 | + <view> | |
| 39 | + <u--textarea border="none" height="96" placeholder="请输入处理结果" v-model="formModel.result" count> | |
| 40 | + </u--textarea> | |
| 41 | + </view> | |
| 42 | + </view> | |
| 43 | + <!-- #endif --> | |
| 44 | + <view class="bottom-button"> | |
| 45 | + <view v-if="handleText.includes(alarmDetail[7].value)" class="u-flex button-item"> | |
| 46 | + <u-button @click="handleSubmit" type="primary" shape="circle" text="处理"></u-button> | |
| 47 | + </view> | |
| 48 | + <view v-if="clearText.includes(alarmDetail[7].value)" class="u-flex button-item"> | |
| 49 | + <u-button @click="handleRemove" type="error" shape="circle" text="清除"></u-button> | |
| 50 | + </view> | |
| 51 | + </view> | |
| 52 | + </view> | |
| 53 | +</template> | |
| 54 | + | |
| 55 | +<script> | |
| 56 | + import { | |
| 57 | + mapActions | |
| 58 | + } from 'vuex' | |
| 59 | + import api from '@/api/index.js' | |
| 60 | + import { | |
| 61 | + alarmSeverity, | |
| 62 | + alarmStatus, | |
| 63 | + operationNumberOrDate, | |
| 64 | + operationString, | |
| 65 | + operationBoolean | |
| 66 | + } from '@/pages/alarm/config/data.js'; | |
| 67 | + import { | |
| 68 | + useShowToast, | |
| 69 | + useNavigateBack | |
| 70 | + } from '@/plugins/utils.js' | |
| 71 | + | |
| 72 | + export default { | |
| 73 | + data() { | |
| 74 | + return { | |
| 75 | + handleText: ['ACTIVE_UNACK', 'CLEARED_UNACK'], | |
| 76 | + clearText: ['ACTIVE_UNACK', 'ACTIVE_ACK'], | |
| 77 | + hasColor: ['告警级别:', '告警状态:'], | |
| 78 | + alarmSeverity, | |
| 79 | + alarmStatus, | |
| 80 | + operationNumberOrDate, | |
| 81 | + operationString, | |
| 82 | + operationBoolean, | |
| 83 | + formModel: { | |
| 84 | + result: '' | |
| 85 | + }, | |
| 86 | + detailId: '', | |
| 87 | + alarmDetail: [], | |
| 88 | + formatDeviceText: '', | |
| 89 | + formatAlarmValueText: '', | |
| 90 | + formatAlarmConditionText: '', | |
| 91 | + }; | |
| 92 | + }, | |
| 93 | + onLoad(e) { | |
| 94 | + if (e.data !== null) { | |
| 95 | + let params = JSON.parse(decodeURIComponent(e.data)); | |
| 96 | + const {deviceName,severity,organizationName,details,type,createdTime,status,id} = params | |
| 97 | + this.detailId = id | |
| 98 | + this.alarmDetail = [{label: '告警场景:',value: type},{label: '告警级别:',value: severity},{label: '所属组织:',value: organizationName},{label: '告警设备:',value: ''},{label: '告警条件:',value: ''},{label: '告警值:',value: ''},{label: '告警时间:',value: createdTime},{label: '告警状态:',value: status},] | |
| 99 | + this.formatAlarmDevice(details) | |
| 100 | + this.formatAlarmValue(details) | |
| 101 | + this.formatAlarmCondition(details) | |
| 102 | + } | |
| 103 | + // 隐藏原生的tabbar | |
| 104 | + uni.hideTabBar(); | |
| 105 | + }, | |
| 106 | + methods: { | |
| 107 | + ...mapActions(['updateBadgeTotal']), | |
| 108 | + setAlarmStatus(value) { | |
| 109 | + return this.alarmSeverity.find(item => item.value === value).label | |
| 110 | + }, | |
| 111 | + setAlarmSeverity(value) { | |
| 112 | + return this.alarmStatus.find(item => item.value === value).label | |
| 113 | + }, | |
| 114 | + returnPrevPage(title) { | |
| 115 | + useShowToast(title) | |
| 116 | + let pages = getCurrentPages(); //获取所有页面栈实例列表 | |
| 117 | + let nowPage = pages[pages.length - 1]; //当前页页面实例 | |
| 118 | + let prevPage = pages[pages.length - 2]; //上一页页面实例 | |
| 119 | + prevPage.$vm.detailStatus = true; | |
| 120 | + }, | |
| 121 | + async handleSubmit() { | |
| 122 | + if (this.formModel.result == '') return uni.$u.toast('请输入处理结果'); | |
| 123 | + const res = await api.alarmApi.postAlarmAckApi(this.detailId) | |
| 124 | + if (res == '') { | |
| 125 | + this.returnPrevPage('处理成功~') | |
| 126 | + setTimeout(() => { | |
| 127 | + useNavigateBack(1) | |
| 128 | + }, 500); | |
| 129 | + } | |
| 130 | + }, | |
| 131 | + async handleRemove() { | |
| 132 | + const res = await api.alarmApi.postAlarmClearApi(this.detailId) | |
| 133 | + if (res == '') { | |
| 134 | + this.returnPrevPage('清除成功~') | |
| 135 | + setTimeout(async () => { | |
| 136 | + useNavigateBack(1) | |
| 137 | + const res = await uni.$u.http.get('/yt/homepage/app?login=true'); | |
| 138 | + if (res) { | |
| 139 | + //异步实时更新告警徽标数 | |
| 140 | + await this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 141 | + } | |
| 142 | + }, 500); | |
| 143 | + } | |
| 144 | + }, | |
| 145 | + //告警值处理 | |
| 146 | + async formatAlarmValue(e) { | |
| 147 | + const keys = Object.keys(e) | |
| 148 | + const dataFormat = await this.handleAlarmDetailFormat(keys); | |
| 149 | + const values = keys.reduce((acc, curr) => { | |
| 150 | + dataFormat.forEach((dataItem => { | |
| 151 | + if (dataItem.tbDeviceId === curr) { | |
| 152 | + const findAttribute = dataItem.attribute.find(findItem => findItem.identifier === e[curr].key) | |
| 153 | + acc.push( | |
| 154 | + `${findAttribute.name}:${e[curr].realValue}${!findAttribute.detail?.dataType?.specs?.unit?.key?'':findAttribute.detail?.dataType?.specs?.unit?.key}` | |
| 155 | + ) | |
| 156 | + } | |
| 157 | + })) | |
| 158 | + return acc | |
| 159 | + }, []) | |
| 160 | + this.formatAlarmValueText = values.join(',') | |
| 161 | + }, | |
| 162 | + //告警条件处理 | |
| 163 | + formatAlarmCondition(e) { | |
| 164 | + const keys = Object.keys(e) | |
| 165 | + const values = keys.reduce((acc, curr) => { | |
| 166 | + acc.push({ | |
| 167 | + login: e[curr].logic, | |
| 168 | + logicValue: e[curr].logicValue | |
| 169 | + }) | |
| 170 | + return acc | |
| 171 | + }, []) | |
| 172 | + const operation = [...operationNumberOrDate, ...operationString, ...operationBoolean] | |
| 173 | + const format = values.map(item => { | |
| 174 | + const findOperation = operation.find(findItem => findItem.value === item.login)?.symbol | |
| 175 | + return findOperation + item.logicValue | |
| 176 | + }) | |
| 177 | + this.formatAlarmConditionText = format.filter(Boolean).join(',') | |
| 178 | + }, | |
| 179 | + //告警设备处理 | |
| 180 | + async formatAlarmDevice(e) { | |
| 181 | + const keys = Object.keys(e) | |
| 182 | + const dataFormat = await this.handleAlarmDetailFormat(keys); | |
| 183 | + if (!dataFormat) this.formatDeviceText = '' | |
| 184 | + if (Array.isArray(dataFormat) && dataFormat.length === 0) this.formatDeviceText = '' | |
| 185 | + this.formatDeviceText = dataFormat.map(item => item.name).join(',') | |
| 186 | + }, | |
| 187 | + async handleAlarmDetailFormat(keys) { | |
| 188 | + const temp = []; | |
| 189 | + for (let item of keys) { | |
| 190 | + if (item === 'key' || item === 'data') return; //旧数据则终止 | |
| 191 | + const deviceDetailRes = await api.deviceApi.getDeviceDetail(item); | |
| 192 | + const { deviceProfileId } = deviceDetailRes; | |
| 193 | + if (!deviceProfileId) return; | |
| 194 | + const attributeRes = await api.deviceApi.getAttribute(deviceProfileId); | |
| 195 | + const dataFormat = this.handleDataFormat(deviceDetailRes, attributeRes); | |
| 196 | + temp.push(dataFormat); | |
| 197 | + } | |
| 198 | + return temp; | |
| 199 | + }, | |
| 200 | + handleDataFormat(deviceDetail, attributes) { | |
| 201 | + const { name,tbDeviceId } = deviceDetail; | |
| 202 | + const attribute = attributes.map((item) => ({ | |
| 203 | + identifier: item.identifier, | |
| 204 | + name: item.name, | |
| 205 | + detail: item.detail | |
| 206 | + })); | |
| 207 | + return { | |
| 208 | + name, | |
| 209 | + tbDeviceId, | |
| 210 | + attribute, | |
| 211 | + }; | |
| 212 | + } | |
| 213 | + } | |
| 214 | + }; | |
| 215 | +</script> | |
| 216 | + | |
| 217 | +<style lang="scss" scoped> | |
| 218 | + @import './static/alarmDetail.scss'; | |
| 219 | + | |
| 220 | + /deep/ .u-button--primary { | |
| 221 | + background-color: #377dff !important; | |
| 222 | + border-color: #377dff !important; | |
| 223 | + } | |
| 224 | +</style> | |
| \ No newline at end of file | ... | ... |
alarm-subpackage/alarm-detail/static/alarmDetail.scss
renamed from
alarmSubPage/alarmDetailPage/static/alarmDetail.scss
| ... | ... | @@ -6,57 +6,67 @@ |
| 6 | 6 | .alarm-detail-column { |
| 7 | 7 | border-radius: 10px; |
| 8 | 8 | width: 688rpx; |
| 9 | - height: 573rpx; | |
| 9 | + height: 688rpx; | |
| 10 | 10 | background-color: #ffffff; |
| 11 | 11 | .detail-column { |
| 12 | - height: 573rpx; | |
| 13 | - justify-content: space-between; | |
| 12 | + width:750rpx; | |
| 14 | 13 | flex-direction: column; |
| 15 | 14 | align-items: center; |
| 16 | - .column { | |
| 17 | - flex-direction: row; | |
| 15 | + .column-line{ | |
| 18 | 16 | display:flex; |
| 19 | - // justify-content: space-between; | |
| 20 | - margin-top: 10rpx; | |
| 21 | - line-height: 68rpx; | |
| 22 | - width: 614rpx; | |
| 23 | - height: 90rpx; | |
| 24 | - text-align: left; | |
| 25 | - border-bottom: 0.1rpx solid #f0f0f0; | |
| 26 | - .device-name{ | |
| 27 | - width:222rpx; | |
| 28 | - } | |
| 29 | - .text { | |
| 30 | - color: #333333; | |
| 31 | - font-size: 15px; | |
| 32 | - } | |
| 33 | - .image { | |
| 34 | - width: 30rpx; | |
| 35 | - height: 30rpx; | |
| 36 | - } | |
| 37 | - .text-alarm-level { | |
| 38 | - color: #333333; | |
| 39 | - font-size: 14px; | |
| 40 | - } | |
| 41 | - .text-alarm-level-lg { | |
| 42 | - color: #333333; | |
| 43 | - font-size: 15px; | |
| 44 | - } | |
| 45 | - .text-alarm-lg { | |
| 46 | - color: #666666; | |
| 47 | - font-size: 14px; | |
| 48 | - } | |
| 49 | - .text-alarm-status { | |
| 50 | - color: #de4437; | |
| 51 | - font-size: 14px; | |
| 17 | + flex-direction: column; | |
| 18 | + .column { | |
| 19 | + display:flex; | |
| 20 | + margin-top: 10rpx; | |
| 21 | + line-height: 68rpx; | |
| 22 | + width:700rpx; | |
| 23 | + height: 74rpx; | |
| 24 | + align-items: center; | |
| 25 | + .device-name{ | |
| 26 | + width:222rpx; | |
| 27 | + } | |
| 28 | + .alarm-text{ | |
| 29 | + width:460rpx; | |
| 30 | + overflow-x: scroll; | |
| 31 | + } | |
| 32 | + | |
| 33 | + .text { | |
| 34 | + color: #333333; | |
| 35 | + font-size: 15px; | |
| 36 | + } | |
| 37 | + .image { | |
| 38 | + width: 30rpx; | |
| 39 | + height: 30rpx; | |
| 40 | + } | |
| 41 | + .text-alarm-level { | |
| 42 | + color: #333333; | |
| 43 | + font-size: 14px; | |
| 44 | + } | |
| 45 | + .text-alarm-level-lg { | |
| 46 | + color: #333333; | |
| 47 | + font-size: 15px; | |
| 48 | + } | |
| 49 | + .text-alarm-lg { | |
| 50 | + color: #666666; | |
| 51 | + font-size: 14px; | |
| 52 | + } | |
| 53 | + .text-alarm-status { | |
| 54 | + color: #de4437; | |
| 55 | + font-size: 14px; | |
| 56 | + } | |
| 52 | 57 | } |
| 58 | + .bottom-line{ | |
| 59 | + border-bottom: 0.1rpx solid #f0f0f0; | |
| 60 | + width:650rpx; | |
| 61 | + } | |
| 53 | 62 | } |
| 63 | + | |
| 54 | 64 | } |
| 55 | 65 | } |
| 56 | 66 | .handle-result { |
| 57 | 67 | color: #333333; |
| 58 | 68 | font-size: 15px; |
| 59 | - margin-top: 20rpx; | |
| 69 | + margin-top: 32rpx; | |
| 60 | 70 | } |
| 61 | 71 | .hanle-main { |
| 62 | 72 | margin-top: 30rpx; |
| ... | ... | @@ -65,3 +75,13 @@ |
| 65 | 75 | height: 273rpx; |
| 66 | 76 | background-color: #ffffff; |
| 67 | 77 | } |
| 78 | +.bottom-button{ | |
| 79 | + margin-top: 44rpx; | |
| 80 | + display: flex; | |
| 81 | + align-items: center; | |
| 82 | + gap:40rpx; | |
| 83 | + justify-content: center; | |
| 84 | + .button-item{ | |
| 85 | + width: 260rpx; | |
| 86 | + } | |
| 87 | +} | |
| \ No newline at end of file | ... | ... |
alarmSubPage/alarmDetailPage/alarmDetail.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <view class="alarm-detail-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view class="alarm-detail-column"> | |
| 6 | - <view class="u-flex detail-column"> | |
| 7 | - <view class="u-flex column"> | |
| 8 | - <text | |
| 9 | - class="text-clip device-name text-org-bold">{{ list.deviceName == null ? '暂无数据' : list.deviceName }}</text> | |
| 10 | - <image class="image" src="/static/alarm-device.png"></image> | |
| 11 | - </view> | |
| 12 | - <view class="column"> | |
| 13 | - <text class="text-org-bold ">告警级别:</text> | |
| 14 | - <text class="text-device-muted" style="color:#DE4437"> | |
| 15 | - {{ | |
| 16 | - list.severity == 'CRITICAL' | |
| 17 | - ? '危险' | |
| 18 | - : list.severity == 'MAJOR' | |
| 19 | - ? '重要' | |
| 20 | - : list.severity == 'MINOR' | |
| 21 | - ? '次要' | |
| 22 | - : list.severity == 'WARNING' | |
| 23 | - ? '警告' | |
| 24 | - : '不确定' | |
| 25 | - }} | |
| 26 | - </text> | |
| 27 | - </view> | |
| 28 | - <view class="column"> | |
| 29 | - <text class="text-org-bold">所属组织:</text> | |
| 30 | - <text | |
| 31 | - class="text-device-muted">{{ list.organizationName == null ? '暂无数据' : list.organizationName }}</text> | |
| 32 | - </view> | |
| 33 | - <view class="column"> | |
| 34 | - <text class="text-org-bold">告警值:</text> | |
| 35 | - <text | |
| 36 | - class="text-device-muted text-clip">{{ list.details == null ? '暂无数据' : formatDetailText(list.details.data) }}</text> | |
| 37 | - </view> | |
| 38 | - <view class="column"> | |
| 39 | - <text class="text-org-bold">告警场景:</text> | |
| 40 | - <text | |
| 41 | - class="text-device-muted text-clip">{{ list.type == null ? '暂无数据' : list.type }}</text> | |
| 42 | - </view> | |
| 43 | - <view class="column"> | |
| 44 | - <text class="text-org-bold">告警时间:</text> | |
| 45 | - <text class="text-device-muted">{{ list.createdTime }}</text> | |
| 46 | - </view> | |
| 47 | - <view class="column"> | |
| 48 | - <text class="text-org-bold">告警状态:</text> | |
| 49 | - <text class="text-device-muted" style="color: #DE4437;"> | |
| 50 | - {{ | |
| 51 | - list.status == 'CLEARED_UNACK' | |
| 52 | - ? '清除未确认' | |
| 53 | - : list.status == 'ACTIVE_UNACK' | |
| 54 | - ? '激活未确认' | |
| 55 | - : list.status == 'CLEARED_ACK' | |
| 56 | - ? '清除已确认' | |
| 57 | - : '激活已确认' | |
| 58 | - }} | |
| 59 | - </text> | |
| 60 | - </view> | |
| 61 | - </view> | |
| 62 | - </view> | |
| 63 | - <!-- #ifdef MP --> | |
| 64 | - <view class="handle-result text-org-bold" style="">处理结果</view> | |
| 65 | - <view class="hanle-main"> | |
| 66 | - <u--form :label-style="{ 'font-size': '0rpx' }" style="padding-left: 26rpx;" labelPosition="left" | |
| 67 | - :model="formModel" ref="form1"> | |
| 68 | - <u-form-item label="." prop="result" ref="item3"> | |
| 69 | - <view style="position: relative;left: -60rpx;"> | |
| 70 | - <u--textarea border="none" height="96" placeholder="请输入处理结果" v-model="formModel.result" count> | |
| 71 | - </u--textarea> | |
| 72 | - </view> | |
| 73 | - </u-form-item> | |
| 74 | - </u--form> | |
| 75 | - </view> | |
| 76 | - <!-- #endif --> | |
| 77 | - <!-- #ifdef APP-PLUS --> | |
| 78 | - <view class="handle-result text-org-bold">处理结果</view> | |
| 79 | - <view class="hanle-main"> | |
| 80 | - <view> | |
| 81 | - <u--textarea border="none" height="96" placeholder="请输入处理结果" v-model="formModel.result" count> | |
| 82 | - </u--textarea> | |
| 83 | - </view> | |
| 84 | - </view> | |
| 85 | - <!-- #endif --> | |
| 86 | - <view style="margin-top: 44rpx;display: flex;align-items: center;justify-content: space-between;"> | |
| 87 | - <view :style="[ | |
| 88 | - { position: list.status !== 'CLEARED_ACK' && list.status !== 'ACTIVE_ACK' ? 'relative' : '' }, | |
| 89 | - { right: list.status !== 'CLEARED_ACK' && list.status !== 'ACTIVE_ACK' ? '-210rpx' : '' } | |
| 90 | - ]" v-if="list.status !== 'CLEARED_ACK' && list.status !== 'ACTIVE_ACK'" class="u-flex" style="width: 260rpx"> | |
| 91 | - <u-button @click="handleSubmit" type="primary" shape="circle" text="处理"></u-button> | |
| 92 | - </view> | |
| 93 | - <view style="width: 30rpx;"></view> | |
| 94 | - <view | |
| 95 | - :style="[{ position: list.status == 'ACTIVE_ACK' ? 'relative' : '' }, { right: list.status == 'ACTIVE_ACK' ? '207rpx' : '' }]" | |
| 96 | - v-if="list.status == 'ACTIVE_ACK'" class="u-flex" style="width: 260rpx"> | |
| 97 | - <u-button @click="handleRemove" type="error" shape="circle" text="清除"></u-button> | |
| 98 | - </view> | |
| 99 | - </view> | |
| 100 | - </view> | |
| 101 | -</template> | |
| 102 | - | |
| 103 | -<script> | |
| 104 | - import { | |
| 105 | - mapActions | |
| 106 | - } from 'vuex' | |
| 107 | - import api from '@/api/index.js' | |
| 108 | - | |
| 109 | - export default { | |
| 110 | - data() { | |
| 111 | - return { | |
| 112 | - formModel: { | |
| 113 | - result: '' | |
| 114 | - }, | |
| 115 | - list: {} | |
| 116 | - }; | |
| 117 | - }, | |
| 118 | - onLoad(e) { | |
| 119 | - if (e.data !== null) { | |
| 120 | - let params = JSON.parse(e.data); | |
| 121 | - this.list = params; | |
| 122 | - } | |
| 123 | - // 隐藏原生的tabbar | |
| 124 | - uni.hideTabBar(); | |
| 125 | - }, | |
| 126 | - methods: { | |
| 127 | - //处理 | |
| 128 | - async handleSubmit() { | |
| 129 | - if (this.formModel.result == '') return uni.$u.toast('请输入处理结果'); | |
| 130 | - const res = await api.alarmApi.postAlarmAckApi(this.list.id) | |
| 131 | - if (res == '') { | |
| 132 | - uni.showToast({ | |
| 133 | - title: '处理成功~', | |
| 134 | - icon: 'none' | |
| 135 | - }); | |
| 136 | - let pages = getCurrentPages(); //获取所有页面栈实例列表 | |
| 137 | - let nowPage = pages[pages.length - 1]; //当前页页面实例 | |
| 138 | - let prevPage = pages[pages.length - 2]; //上一页页面实例 | |
| 139 | - prevPage.$vm.detailStatus = true; | |
| 140 | - setTimeout(() => { | |
| 141 | - uni.navigateBack({ | |
| 142 | - delta: 1 | |
| 143 | - }); | |
| 144 | - }, 500); | |
| 145 | - } | |
| 146 | - }, | |
| 147 | - // 清除 | |
| 148 | - async handleRemove() { | |
| 149 | - const res = await api.alarmApi.postAlarmClearApi(this.list.id) | |
| 150 | - if (res == '') { | |
| 151 | - uni.showToast({ | |
| 152 | - title: '清除成功~', | |
| 153 | - icon: 'none' | |
| 154 | - }); | |
| 155 | - let pages = getCurrentPages(); //获取所有页面栈实例列表 | |
| 156 | - let nowPage = pages[pages.length - 1]; //当前页页面实例 | |
| 157 | - let prevPage = pages[pages.length - 2]; //上一页页面实例 | |
| 158 | - prevPage.$vm.detailStatus = true; | |
| 159 | - setTimeout(async () => { | |
| 160 | - uni.navigateBack({ | |
| 161 | - delta: 1 | |
| 162 | - }); | |
| 163 | - const res = await uni.$u.http.get('/yt/homepage/app?login=true'); | |
| 164 | - if (res) { | |
| 165 | - //异步实时更新告警徽标数 | |
| 166 | - await this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 167 | - } | |
| 168 | - }, 500); | |
| 169 | - } | |
| 170 | - }, | |
| 171 | - ...mapActions(['updateBadgeTotal']), | |
| 172 | - formatDetailText(e) { | |
| 173 | - //去除字符串双引号 | |
| 174 | - const jsonStr = JSON.stringify(e); | |
| 175 | - const str = jsonStr.substring(1, jsonStr.length - 1); | |
| 176 | - const newStr = str.replace(/\"/g, ''); | |
| 177 | - return newStr.slice(0,26); | |
| 178 | - } | |
| 179 | - } | |
| 180 | - }; | |
| 181 | -</script> | |
| 182 | - | |
| 183 | -<style lang="scss" scoped> | |
| 184 | - @import './static/alarmDetail.scss'; | |
| 185 | - | |
| 186 | - /deep/ .u-button--primary { | |
| 187 | - background-color: #377dff !important; | |
| 188 | - border-color: #377dff !important; | |
| 189 | - } | |
| 190 | -</style> |
| ... | ... | @@ -11,6 +11,30 @@ const getDeviceApi = (urlParams, data) => { |
| 11 | 11 | return uni.$u.http.post(`/yt/device?page=${page}&pageSize=${pageSize}`, data); |
| 12 | 12 | }; |
| 13 | 13 | |
| 14 | -export default { | |
| 15 | - getDeviceApi | |
| 14 | +// 设备详情 | |
| 15 | +const getDeviceDetail = (id) => { | |
| 16 | + return uni.$u.http.get(`/yt/device/${id}`); | |
| 17 | +}; | |
| 18 | + | |
| 19 | +//设备属性 | |
| 20 | +const getAttribute = (deviceProfileId) => { | |
| 21 | + return uni.$u.http.get(`/yt/device/attributes/${deviceProfileId}`); | |
| 22 | +}; | |
| 23 | + | |
| 24 | +//命令下发 | |
| 25 | +const issueCommand = (type, tbDeviceId, data) => { | |
| 26 | + return uni.$u.http.post(`/rpc/${type==='OneWay'?'oneway':'twoway'}/${tbDeviceId}`, data) | |
| 16 | 27 | } |
| 28 | + | |
| 29 | +//获取命令下发记录 | |
| 30 | +const getRpcRecord = (params) => { | |
| 31 | + return uni.$u.http.get('/yt/rpc', params); | |
| 32 | +}; | |
| 33 | + | |
| 34 | +export default { | |
| 35 | + getDeviceApi, | |
| 36 | + getDeviceDetail, | |
| 37 | + getAttribute, | |
| 38 | + issueCommand, | |
| 39 | + getRpcRecord | |
| 40 | +} | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -20,9 +20,16 @@ const getConfigurationApi = (params = {}) => { |
| 20 | 20 | .get('/yt/configuration/center', params) |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +//获取组织列表 | |
| 24 | +const getMeOrgListApi = () => { | |
| 25 | + return uni.$u.http | |
| 26 | + .get('/yt/organization/me/list') | |
| 27 | +} | |
| 28 | + | |
| 23 | 29 | export default { |
| 24 | 30 | getHomeStatisticsApi, |
| 25 | 31 | getCameraApi, |
| 26 | 32 | byCameraIdGetDetailApi, |
| 27 | - getConfigurationApi | |
| 33 | + getConfigurationApi, | |
| 34 | + getMeOrgListApi | |
| 28 | 35 | } | ... | ... |
| ... | ... | @@ -3,12 +3,18 @@ const getPlateCustomApi = () => { |
| 3 | 3 | return uni.$u.http.get("/yt/app_design/get") |
| 4 | 4 | }; |
| 5 | 5 | |
| 6 | -//第三方账号绑定API | |
| 6 | +//第三方账号登录API | |
| 7 | 7 | const getThirdLoginApi = (code) => { |
| 8 | 8 | return uni.$u.http.get(`/yt/third/login/${code}`) |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | -//获取个人信息API | |
| 11 | +//第三方账号绑定API | |
| 12 | +const postThirdLoginApi = (data = {}) => { | |
| 13 | + return uni.$u.http | |
| 14 | + .post("/yt/third/bind", data) | |
| 15 | +}; | |
| 16 | + | |
| 17 | +//设置个人信息API | |
| 12 | 18 | const setUserInfoApi = () => { |
| 13 | 19 | return uni.$u.http.get("/yt/user/me/info") |
| 14 | 20 | }; |
| ... | ... | @@ -52,6 +58,18 @@ const deleteBindApi = (data = {}) => { |
| 52 | 58 | return uni.$u.http.delete('/yt/third', data) |
| 53 | 59 | } |
| 54 | 60 | |
| 61 | +//获取手机验证码API | |
| 62 | +const postPhoneCodeApi = (phone, data = {}) => { | |
| 63 | + return uni.$u.http | |
| 64 | + .post(`/yt/noauth/send_login_code/${phone}`, data) | |
| 65 | +} | |
| 66 | + | |
| 67 | +//手机登录API | |
| 68 | +const postPhoneLoginApi = (data = {}) => { | |
| 69 | + return uni.$u.http | |
| 70 | + .post('/yt/auth/code/login', data) | |
| 71 | +} | |
| 72 | + | |
| 55 | 73 | export default { |
| 56 | 74 | getPlateCustomApi, |
| 57 | 75 | getThirdLoginApi, |
| ... | ... | @@ -62,5 +80,8 @@ export default { |
| 62 | 80 | postCodeApi, |
| 63 | 81 | postResetCodeApi, |
| 64 | 82 | postPersonalInfoApi, |
| 65 | - deleteBindApi | |
| 83 | + deleteBindApi, | |
| 84 | + postPhoneCodeApi, | |
| 85 | + postPhoneLoginApi, | |
| 86 | + postThirdLoginApi | |
| 66 | 87 | } | ... | ... |
components/common/header-org.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="header-org"> | |
| 3 | + <view @click="$emit('openOrg')" class="org-item"> | |
| 4 | + <view class="u-flex org-contact"><text class="text">组织关系</text></view> | |
| 5 | + <view class="u-flex org-device"> | |
| 6 | + <image class="device-image" :src="imageSrc"></image> | |
| 7 | + <text class="device-text">摄像头数:{{ total }}</text> | |
| 8 | + </view> | |
| 9 | + </view> | |
| 10 | + <view class="org-item"> | |
| 11 | + <image class="image" src="/static/arrow-right.png"></image> | |
| 12 | + </view> | |
| 13 | + </view> | |
| 14 | +</template> | |
| 15 | + | |
| 16 | +<script> | |
| 17 | + export default { | |
| 18 | + props: { | |
| 19 | + total: Number, | |
| 20 | + imageSrc: String | |
| 21 | + } | |
| 22 | + } | |
| 23 | +</script> | |
| 24 | + | |
| 25 | +<style lang="scss" scoped> | |
| 26 | + .header-org { | |
| 27 | + width: 750rpx; | |
| 28 | + height: 150rpx; | |
| 29 | + margin-top: 1rpx; | |
| 30 | + background-color: #fff; | |
| 31 | + display: flex; | |
| 32 | + flex-direction: row; | |
| 33 | + justify-content: space-between; | |
| 34 | + position: fixed; | |
| 35 | + z-index: 999999; | |
| 36 | + top: -1rpx; | |
| 37 | + | |
| 38 | + .org-item { | |
| 39 | + width: 350rpx; | |
| 40 | + height: 200rpx; | |
| 41 | + | |
| 42 | + .org-contact { | |
| 43 | + flex-direction: row; | |
| 44 | + margin-top: 26rpx; | |
| 45 | + margin-left: 15rpx; | |
| 46 | + | |
| 47 | + .text { | |
| 48 | + color: #333333; | |
| 49 | + font-size: 15px; | |
| 50 | + margin-left: 14rpx; | |
| 51 | + } | |
| 52 | + } | |
| 53 | + | |
| 54 | + .org-device { | |
| 55 | + margin-top: 23rpx; | |
| 56 | + margin-left: 15rpx; | |
| 57 | + flex-direction: row; | |
| 58 | + | |
| 59 | + .device-image { | |
| 60 | + margin-left: 14rpx; | |
| 61 | + width: 30rpx; | |
| 62 | + height: 30rpx; | |
| 63 | + } | |
| 64 | + | |
| 65 | + .device-text { | |
| 66 | + margin-left: 10rpx; | |
| 67 | + color: #666666; | |
| 68 | + font-size: 12px; | |
| 69 | + } | |
| 70 | + } | |
| 71 | + | |
| 72 | + .image { | |
| 73 | + width: 6px; | |
| 74 | + height: 10px; | |
| 75 | + float: right; | |
| 76 | + margin-right: 34rpx; | |
| 77 | + margin-top: 37rpx; | |
| 78 | + } | |
| 79 | + } | |
| 80 | + } | |
| 81 | +</style> | |
| \ No newline at end of file | ... | ... |
components/common/header-search.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <u-sticky> | |
| 3 | + <view class="device-top"> | |
| 4 | + <view class="search"> | |
| 5 | + <view> | |
| 6 | + <view class="search-left"> | |
| 7 | + <slot></slot> | |
| 8 | + </view> | |
| 9 | + </view> | |
| 10 | + <view @click="$emit('openSearchDialog')" class="search-right"> | |
| 11 | + <text>筛选</text> | |
| 12 | + <image src="../../static/shaixuan.png" /> | |
| 13 | + </view> | |
| 14 | + </view> | |
| 15 | + <u-line /> | |
| 16 | + <view class="org"> | |
| 17 | + <u-cell @click="$emit('openOrg')" isLink title="组织关系" :border="false"> | |
| 18 | + <view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;"> | |
| 19 | + <image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image> | |
| 20 | + <view style="margin-left: 10rpx; color: #666;"> | |
| 21 | + {{totalText}} | |
| 22 | + <text style="margin-left: 20rpx;">{{ total }}</text> | |
| 23 | + </view> | |
| 24 | + </view> | |
| 25 | + </u-cell> | |
| 26 | + </view> | |
| 27 | + </view> | |
| 28 | + </u-sticky> | |
| 29 | +</template> | |
| 30 | + | |
| 31 | +<script> | |
| 32 | + export default { | |
| 33 | + props: { | |
| 34 | + total: Number, | |
| 35 | + totalText: [Number, String] | |
| 36 | + } | |
| 37 | + } | |
| 38 | +</script> | |
| 39 | + | |
| 40 | +<style lang="scss" scoped> | |
| 41 | + /deep/ .u-button--primary { | |
| 42 | + background-color: #377dff !important; | |
| 43 | + border-color: #377dff !important; | |
| 44 | + } | |
| 45 | + | |
| 46 | + /deep/ .u-button--info { | |
| 47 | + background-color: #e3e3e5 !important; | |
| 48 | + border-color: #e3e3e5 !important; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /deep/ .u-cell__right-icon-wrap { | |
| 52 | + margin-top: -55rpx !important; | |
| 53 | + } | |
| 54 | + | |
| 55 | + /deep/ .uni-calendar--fixed { | |
| 56 | + bottom: 172rpx !important; | |
| 57 | + } | |
| 58 | + | |
| 59 | + .pop-no-scroll { | |
| 60 | + overflow: hidden; | |
| 61 | + position: fixed; | |
| 62 | + height: 100%; | |
| 63 | + width: 100%; | |
| 64 | + } | |
| 65 | + | |
| 66 | + .device-top { | |
| 67 | + padding: 10rpx 30rpx; | |
| 68 | + background-color: #fff; | |
| 69 | + | |
| 70 | + .search { | |
| 71 | + display: flex; | |
| 72 | + justify-content: space-between; | |
| 73 | + padding-bottom: 10rpx; | |
| 74 | + | |
| 75 | + .search-left { | |
| 76 | + width: 580rpx; | |
| 77 | + background-color: #f8f9fa; | |
| 78 | + border-radius: 200rpx; | |
| 79 | + } | |
| 80 | + | |
| 81 | + .search-right { | |
| 82 | + display: flex; | |
| 83 | + align-items: center; | |
| 84 | + | |
| 85 | + text { | |
| 86 | + color: #333; | |
| 87 | + font-size: 14px; | |
| 88 | + } | |
| 89 | + | |
| 90 | + image { | |
| 91 | + width: 40rpx; | |
| 92 | + height: 40rpx; | |
| 93 | + } | |
| 94 | + } | |
| 95 | + } | |
| 96 | + } | |
| 97 | +</style> | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -228,7 +228,6 @@ export default { |
| 228 | 228 | if (pageLen == 1 && !mainPagePath.includes(currentPages[0].route)) { |
| 229 | 229 | this.firstPage = true; |
| 230 | 230 | this.iconLeft = 'home'; |
| 231 | - console.log(this.firstPage, 'this.firstPage'); | |
| 232 | 231 | } |
| 233 | 232 | }, |
| 234 | 233 | methods: { |
| ... | ... | @@ -273,7 +272,6 @@ export default { |
| 273 | 272 | //设置手机状态栏颜色 |
| 274 | 273 | settingColor() { |
| 275 | 274 | let navColor = this.navFontColor; |
| 276 | - console.log(navColor, 'settingColor'); | |
| 277 | 275 | let frontColor = '#000000'; |
| 278 | 276 | if (whiteList.includes(navColor)) { |
| 279 | 277 | frontColor = '#ffffff'; | ... | ... |
| ... | ... | @@ -9,10 +9,10 @@ import { |
| 9 | 9 | * socketPrefix websocket前缀 ((https, wss),( http, ws)) |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | -const baseUrl = "https://demo.thingskit.com/api"; | |
| 13 | -const baseDrawioUrl = "https://demo.thingskit.com/thingskit-scada"; | |
| 14 | -const baseWebSocketUrl = "demo.thingskit.com"; | |
| 15 | -const socketPrefix = "wss"; | |
| 12 | +const baseUrl = "http://222.180.200.114:48080/api"; | |
| 13 | +const baseDrawioUrl = "http://222.180.200.114:9527/thingskit-scada"; | |
| 14 | +const baseWebSocketUrl = "222.180.200.114:48080"; | |
| 15 | +const socketPrefix = "ws"; | |
| 16 | 16 | |
| 17 | 17 | let systemInfo = { |
| 18 | 18 | ...getTabbarHeight(), |
| ... | ... | @@ -51,4 +51,4 @@ const courtConfig = { |
| 51 | 51 | sk: "", |
| 52 | 52 | }, |
| 53 | 53 | }; |
| 54 | -export default Object.assign({}, courtConfig); | |
| 54 | +export default Object.assign({}, courtConfig); | ... | ... |
| ... | ... | @@ -103,11 +103,11 @@ uni.$u.http.interceptors.response.use( |
| 103 | 103 | const routers = getCurrentPages(); |
| 104 | 104 | const currentRoute = routers[routers.length - 1].route; |
| 105 | 105 | const isLoginPage = currentRoute.includes( |
| 106 | - "publicLoginSubPage/public/login" | |
| 106 | + "login-subpackage/public/login" | |
| 107 | 107 | ); |
| 108 | 108 | !isLoginPage && |
| 109 | 109 | uni.reLaunch({ |
| 110 | - url: "/publicLoginSubPage/public/login", | |
| 110 | + url: "/login-subpackage/public/login", | |
| 111 | 111 | }); |
| 112 | 112 | // 清空登录信息 |
| 113 | 113 | store.commit("emptyUserInfo"); | ... | ... |
constant/index.js
0 → 100644
device-subpackage/device-detail/api/index.js
renamed from
deviceSubPage/deviceDetailPage/api/index.js
| 1 | -// 获取某个Key的历史数据 | |
| 2 | -const getUrlParams = (params) => { | |
| 3 | - return Object.keys(params).reduce((prev, next, currentIndex) => { | |
| 4 | - if (params[next]) { | |
| 5 | - return prev += `${!currentIndex ? '?' : '&'}${next}=${params[next]}` | |
| 6 | - } | |
| 7 | - return prev | |
| 8 | - }, '') | |
| 9 | -} | |
| 10 | - | |
| 11 | -export function getHistoryData(params) { | |
| 12 | - let { | |
| 13 | - entityId | |
| 14 | - } = params | |
| 15 | - params = getUrlParams(params) | |
| 16 | - return uni.$u.http.get( | |
| 17 | - `/plugins/telemetry/DEVICE/${entityId}/values/timeseries${params}` | |
| 18 | - ); | |
| 19 | -} | |
| 20 | - | |
| 21 | - | |
| 22 | - | |
| 23 | -// 获取当前设备的key | |
| 24 | -export function getDeviceKeys(id) { | |
| 25 | - return uni.$u.http.get(`/plugins/telemetry/DEVICE/${id}/keys/timeseries`); | |
| 26 | -}; | |
| 27 | - | |
| 28 | -export function issueCommand(type, tbDeviceId, data) { | |
| 29 | - return uni.$u.http.post(`/rpc/${type==='OneWay'?'oneway':'twoway'}/${tbDeviceId}`, data) | |
| 1 | +// 获取某个Key的历史数据 | |
| 2 | +const getUrlParams = (params) => { | |
| 3 | + return Object.keys(params).reduce((prev, next, currentIndex) => { | |
| 4 | + if (params[next]) { | |
| 5 | + return prev += `${!currentIndex ? '?' : '&'}${next}=${params[next]}` | |
| 6 | + } | |
| 7 | + return prev | |
| 8 | + }, '') | |
| 30 | 9 | } |
| 10 | + | |
| 11 | +export function getHistoryData(params) { | |
| 12 | + let { | |
| 13 | + entityId | |
| 14 | + } = params | |
| 15 | + params = getUrlParams(params) | |
| 16 | + return uni.$u.http.get( | |
| 17 | + `/plugins/telemetry/DEVICE/${entityId}/values/timeseries${params}` | |
| 18 | + ); | |
| 19 | +} | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | +// 获取当前设备的key | |
| 24 | +export function getDeviceKeys(id) { | |
| 25 | + return uni.$u.http.get(`/plugins/telemetry/DEVICE/${id}/keys/timeseries`); | |
| 26 | +}; | ... | ... |
| 1 | +<template> | |
| 2 | + <view class="alert-page"> | |
| 3 | + <!-- 告警头部 --> | |
| 4 | + <view class="filter-button" @click="openSearchDialog"> | |
| 5 | + <text>筛选</text> | |
| 6 | + <image src="/static/shaixuan.png" /> | |
| 7 | + </view> | |
| 8 | + <!-- 告警分页 --> | |
| 9 | + <mescroll-uni height="700rpx;" ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" | |
| 10 | + @down="downCallback" @up="upCallback"> | |
| 11 | + <alarm-item :list="list" @openAlertDetail="openAlertDetail"></alarm-item> | |
| 12 | + <mescroll-empty v-if="!list.length" /> | |
| 13 | + </mescroll-uni> | |
| 14 | + <view style="height: 20rpx"></view> | |
| 15 | + <!-- 告警筛选 --> | |
| 16 | + <alarm-popup ref="alarmPopupRef" :show="show" @close="close" @queryCondition="getQueryCondition"></alarm-popup> | |
| 17 | + </view> | |
| 18 | +</template> | |
| 19 | +<script> | |
| 20 | + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 21 | + import api from '@/api/index.js' | |
| 22 | + import alarmItem from '@/pages/alarm/components/alarm-item.vue' | |
| 23 | + import alarmPopup from '@/pages/alarm/components/alarm-popup.vue' | |
| 24 | + import { | |
| 25 | + useNavigateTo | |
| 26 | + } from '@/plugins/utils.js' | |
| 27 | + | |
| 28 | + export default { | |
| 29 | + mixins: [MescrollMixin], | |
| 30 | + components: { | |
| 31 | + alarmItem, | |
| 32 | + alarmPopup | |
| 33 | + }, | |
| 34 | + props: { | |
| 35 | + deviceId: { | |
| 36 | + type: String, | |
| 37 | + default: '' | |
| 38 | + } | |
| 39 | + }, | |
| 40 | + data() { | |
| 41 | + return { | |
| 42 | + show: false, | |
| 43 | + list: [], | |
| 44 | + total: 0, | |
| 45 | + downOption: { | |
| 46 | + auto: true //是否在初始化后,自动执行downCallback; 默认true | |
| 47 | + }, | |
| 48 | + upOption: { | |
| 49 | + auto: false // 不自动加载 | |
| 50 | + }, | |
| 51 | + page: { | |
| 52 | + num: 0, | |
| 53 | + size: 10 | |
| 54 | + }, | |
| 55 | + conditions: {}, | |
| 56 | + }; | |
| 57 | + }, | |
| 58 | + methods: { | |
| 59 | + disabledScroll() { | |
| 60 | + return; | |
| 61 | + }, | |
| 62 | + getQueryCondition(value) { | |
| 63 | + this.conditions = value | |
| 64 | + this.conditions.deviceId = this.deviceId | |
| 65 | + this.loadData(1, this.conditions); | |
| 66 | + this.close() | |
| 67 | + }, | |
| 68 | + resetQuery() { | |
| 69 | + this.page.num = 1; | |
| 70 | + this.$nextTick(() => { | |
| 71 | + this.$refs.alarmPopupRef.resetQuery() | |
| 72 | + }) | |
| 73 | + this.conditions = {} | |
| 74 | + }, | |
| 75 | + downCallback() { | |
| 76 | + this.list = []; | |
| 77 | + this.page.num = 1; | |
| 78 | + this.resetQuery(); | |
| 79 | + this.loadData(this.page.num, { | |
| 80 | + deviceId: this.deviceId | |
| 81 | + }); | |
| 82 | + }, | |
| 83 | + upCallback() { | |
| 84 | + const deviceId = { | |
| 85 | + deviceId: this.deviceId | |
| 86 | + } | |
| 87 | + const condition = Object.values(this.conditions) | |
| 88 | + if (condition.length === 0) { | |
| 89 | + this.page.num += 1; | |
| 90 | + this.loadData(this.page.num, { | |
| 91 | + ...deviceId | |
| 92 | + }); | |
| 93 | + } else if (condition.filter(Boolean).length > 0) { | |
| 94 | + this.page.num += 1; | |
| 95 | + this.loadData(this.page.num, { | |
| 96 | + ...this.conditions, | |
| 97 | + ...deviceId | |
| 98 | + }); | |
| 99 | + } else { | |
| 100 | + this.page.num += 1; | |
| 101 | + this.loadData(this.page.num, { | |
| 102 | + ...deviceId | |
| 103 | + }); | |
| 104 | + } | |
| 105 | + }, | |
| 106 | + async loadData(page, param) { | |
| 107 | + let that = this; | |
| 108 | + let params = { | |
| 109 | + page, | |
| 110 | + pageSize: 10, | |
| 111 | + ...param | |
| 112 | + }; | |
| 113 | + const res = await api.alarmApi.getAlarmApi({ | |
| 114 | + params, | |
| 115 | + custom: { | |
| 116 | + load: false | |
| 117 | + } | |
| 118 | + }) | |
| 119 | + if (!res) return | |
| 120 | + uni.stopPullDownRefresh(); | |
| 121 | + that.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数) | |
| 122 | + that.alarmTotal = res.total; | |
| 123 | + if (page == 1) { | |
| 124 | + that.list = res.items; | |
| 125 | + } else { | |
| 126 | + that.list = that.list.concat(res.items); | |
| 127 | + } | |
| 128 | + }, | |
| 129 | + openSearchDialog() { | |
| 130 | + this.show = true; | |
| 131 | + this.resetQuery(); | |
| 132 | + }, | |
| 133 | + close() { | |
| 134 | + this.show = false; | |
| 135 | + }, | |
| 136 | + openAlertDetail(e) { | |
| 137 | + useNavigateTo('/alarm-subpackage/alarm-detail/alarm-detail?data=', e) | |
| 138 | + } | |
| 139 | + } | |
| 140 | + }; | |
| 141 | +</script> | |
| 142 | + | |
| 143 | +<style lang="scss" scoped> | |
| 144 | + .filter-button { | |
| 145 | + margin: 0 20rpx; | |
| 146 | + font-size: 12px; | |
| 147 | + width: 160rpx; | |
| 148 | + height: 64rpx; | |
| 149 | + border-radius: 32rpx; | |
| 150 | + display: flex; | |
| 151 | + justify-content: center; | |
| 152 | + align-items: center; | |
| 153 | + background: #f0f1f2; | |
| 154 | + color: #666; | |
| 155 | + | |
| 156 | + image { | |
| 157 | + width: 28rpx; | |
| 158 | + height: 28rpx; | |
| 159 | + margin-left: 4rpx; | |
| 160 | + } | |
| 161 | + } | |
| 162 | +</style> | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/components/basic-info.vue
renamed from
deviceSubPage/deviceDetailPage/tabDetail/basicInfo.vue
| 1 | -<template> | |
| 2 | - <view class="basic-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module /> | |
| 5 | - <view class="basic-title"> | |
| 6 | - <view class="u-flex"> | |
| 7 | - <view style="padding-left: 32rpx;"> | |
| 8 | - <u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick" name="map-fill"> | |
| 9 | - </u-icon> | |
| 10 | - </view> | |
| 11 | - <view class="text-clip" style="margin-left: 20rpx;width:370rpx"> | |
| 12 | - {{ deviceDetail.alias? deviceDetail.alias: deviceDetail.name }} | |
| 13 | - </view> | |
| 14 | - <view style="margin-left: 20rpx; font-size: 14px;" | |
| 15 | - :style="{ color: deviceDetail.deviceState === 'INACTIVE' ? '#666' : deviceDetail.deviceState === 'ONLINE' ? '#377DFF' : '#DE4437' }"> | |
| 16 | - {{ deviceStatus }} | |
| 17 | - </view> | |
| 18 | - </view> | |
| 19 | - <view style="margin-right: 20rpx;" | |
| 20 | - v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.deviceType !== 'SENSOR'"> | |
| 21 | - <!-- #ifdef MP --> | |
| 22 | - <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModalBtn" /> | |
| 23 | - <!-- #endif --> | |
| 24 | - <!-- #ifdef APP-PLUS --> | |
| 25 | - <view class="cu-item" @tap="showModal" data-target="Modal"> | |
| 26 | - <text>下发命令</text> | |
| 27 | - </view> | |
| 28 | - <!-- #endif --> | |
| 29 | - </view> | |
| 30 | - </view> | |
| 31 | - <view class="detail"> | |
| 32 | - <view class="detail-item"> | |
| 33 | - <view class="detail-label">设备编号</view> | |
| 34 | - <view class="detail-value">{{ deviceDetail.sn }}</view> | |
| 35 | - </view> | |
| 36 | - <u-line length="90%" margin="0 auto"></u-line> | |
| 37 | - <view class="detail-item"> | |
| 38 | - <view class="detail-label">设备类型</view> | |
| 39 | - <view class="detail-value">{{ deviceType }}</view> | |
| 40 | - </view> | |
| 41 | - <u-line length="90%" margin="0 auto"></u-line> | |
| 42 | - <view class="detail-item"> | |
| 43 | - <view class="detail-label">所属组织</view> | |
| 44 | - <view class="detail-value">{{ deviceDetail.organizationDTO.name }}</view> | |
| 45 | - </view> | |
| 46 | - <u-line length="90%" margin="0 auto"></u-line> | |
| 47 | - <view class="detail-item"> | |
| 48 | - <view class="detail-label">最后连接时间</view> | |
| 49 | - <view class="detail-value">{{ formatLastOnlineTime }}</view> | |
| 50 | - </view> | |
| 51 | - <u-line length="90%" margin="0 auto"></u-line> | |
| 52 | - <view class="detail-item"> | |
| 53 | - <view class="detail-label">是否告警</view> | |
| 54 | - <view class="detail-value">{{ alarmStatus }}</view> | |
| 55 | - </view> | |
| 56 | - <u-line length="90%" margin="0 auto"></u-line> | |
| 57 | - <view class="detail-item"> | |
| 58 | - <view class="detail-label">设备描述</view> | |
| 59 | - <view class="detail-value">{{ deviceDetail.description }}</view> | |
| 60 | - </view> | |
| 61 | - </view> | |
| 62 | - <!-- 下发命令 --> | |
| 63 | - <!-- #ifdef APP-PLUS --> | |
| 64 | - <view v-show="showNodal" class="cu-modal" :class="modalName=='Modal'?'show':''"> | |
| 65 | - <view class="cu-dialog" style=""> | |
| 66 | - <view class="modal_main"> | |
| 67 | - <view class='nav-list margin-top'> | |
| 68 | - <view style="width: 100%; padding: 0 30rpx;"> | |
| 69 | - <view style="text-align: center; font-weight:700;margin-top: 40rpx;">命令下发</view> | |
| 70 | - <view style="height: 20rpx;"></view> | |
| 71 | - <view class="u-flex"> | |
| 72 | - <text | |
| 73 | - style="color: #333; font-size: 14px;font-weight:700;margin-right: 30rpx;">下发类型:</text> | |
| 74 | - <view> | |
| 75 | - <radio-group style="display: flex;" @change="radioChange"> | |
| 76 | - <label class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in items" | |
| 77 | - :key="item.value"> | |
| 78 | - <view style="display: flex"> | |
| 79 | - <view style="margin-left: 10rpx;"> | |
| 80 | - <radio :value="item.value" :checked="index === current" /> | |
| 81 | - </view> | |
| 82 | - <view style="width:10rpx"></view> | |
| 83 | - <view style="margin-left: 10rpx;">{{item.name}}</view> | |
| 84 | - </view> | |
| 85 | - </label> | |
| 86 | - </radio-group> | |
| 87 | - </view> | |
| 88 | - </view> | |
| 89 | - <view style="margin-top: 15rpx"> | |
| 90 | - <view class="cusAppplusContent"> | |
| 91 | - <textarea v-model="inputCommandVal" placeholder="请输入下发内容(json格式)" /> | |
| 92 | - </view> | |
| 93 | - </view> | |
| 94 | - <view class="button-group"> | |
| 95 | - <view> | |
| 96 | - <view class="cusAppplusCancelBtn" @click="cancelCommand"><text | |
| 97 | - style="color: #333333">取消</text> | |
| 98 | - </view> | |
| 99 | - </view> | |
| 100 | - <view> | |
| 101 | - <view class="cusAppplusConfrimBtn" @click="confirmCommand"> | |
| 102 | - <text style="color:white">确认</text> | |
| 103 | - </view> | |
| 104 | - </view> | |
| 105 | - </view> | |
| 106 | - <view style="height:30rpx"></view> | |
| 107 | - </view> | |
| 108 | - </view> | |
| 109 | - </view> | |
| 110 | - </view> | |
| 111 | - </view> | |
| 112 | - <!-- #endif --> | |
| 113 | - <!-- #ifdef MP --> | |
| 114 | - <u-modal :show="showModel" closeOnClickOverlay :showConfirmButton="false" width="720rpx" @close="hiddenModal" | |
| 115 | - @touchmove.stop.prevent="disabledScroll"> | |
| 116 | - <view style="width: 100%; padding: 0 30rpx;"> | |
| 117 | - <view style="text-align: center; font-weight:700;margin-bottom: 40rpx;">命令下发</view> | |
| 118 | - <view class="u-flex"> | |
| 119 | - <text style="color: #333; font-size: 14px;font-weight:700;margin-right: 30rpx;">下发类型:</text> | |
| 120 | - | |
| 121 | - <u-radio-group v-model="commandType" placement="row"> | |
| 122 | - <u-radio activeColor="#3388FF" label="单向" name="OneWay"></u-radio> | |
| 123 | - <view style="margin: 0 20rpx;"></view> | |
| 124 | - <u-radio activeColor="#3388FF" label="双向" name="TwoWay"></u-radio> | |
| 125 | - </u-radio-group> | |
| 126 | - </view> | |
| 127 | - <view style="margin-top: 28rpx;width: 100%;"> | |
| 128 | - <div class="u-flex u-row-between"> | |
| 129 | - <u--textarea :placeholder="`请输入下发内容${isShowTCP?'(字符串格式)':'(json格式)'}`" v-model="inputCommandVal" /> | |
| 130 | - <u-icon v-if="!isShowTCP" @click="handleCopy(copyTextValue)" name="question-circle" color="#2979ff" size="28" | |
| 131 | - class="ml-10"> | |
| 132 | - </u-icon> | |
| 133 | - </div> | |
| 134 | - </view> | |
| 135 | - | |
| 136 | - <view class="button-group"> | |
| 137 | - <view> | |
| 138 | - <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="取消" | |
| 139 | - @click="cancelCommand"></u-button> | |
| 140 | - </view> | |
| 141 | - <view> | |
| 142 | - <u-button color="#3388ff" shape="circle" text="确认" @click="confirmCommand"></u-button> | |
| 143 | - </view> | |
| 144 | - </view> | |
| 145 | - </view> | |
| 146 | - </u-modal> | |
| 147 | - <!-- #endif --> | |
| 148 | - </view> | |
| 149 | -</template> | |
| 150 | - | |
| 151 | -<script> | |
| 152 | - import { | |
| 153 | - formatToDate | |
| 154 | - } from '@/plugins/utils.js'; | |
| 155 | - import { | |
| 156 | - issueCommand | |
| 157 | - } from '../api/index.js'; | |
| 158 | - export default { | |
| 159 | - props: { | |
| 160 | - deviceDetail: { | |
| 161 | - type: Object, | |
| 162 | - default: () => ({}) | |
| 163 | - } | |
| 164 | - }, | |
| 165 | - data() { | |
| 166 | - return { | |
| 167 | - copyTextValue: { | |
| 168 | - "method": "methodThingskit", | |
| 169 | - "params": { | |
| 170 | - "pin": 7, | |
| 171 | - "value": 1 | |
| 172 | - } | |
| 173 | - }, | |
| 174 | - showNodal: false, | |
| 175 | - items: [{ | |
| 176 | - value: 'OneWay', | |
| 177 | - name: '单向', | |
| 178 | - checked: 'true' | |
| 179 | - }, | |
| 180 | - { | |
| 181 | - value: 'TwoWay', | |
| 182 | - name: '双向' | |
| 183 | - }, | |
| 184 | - ], | |
| 185 | - current: 0, | |
| 186 | - modalName: null, | |
| 187 | - showModel: false, | |
| 188 | - commandType: 'OneWay', | |
| 189 | - commandValue: {}, | |
| 190 | - inputCommandVal: '', | |
| 191 | - isShowTCP:false,//用于下发命令时判断是否是TCP/UDP | |
| 192 | - }; | |
| 193 | - }, | |
| 194 | - computed: { | |
| 195 | - deviceStatus(){ | |
| 196 | - return this.deviceDetail.deviceState === 'INACTIVE' ? '待激活' : this.deviceDetail.deviceState === 'ONLINE' ? '在线' : '离线' | |
| 197 | - }, | |
| 198 | - deviceType() { | |
| 199 | - return this.deviceDetail.deviceType === 'DIRECT_CONNECTION' ? | |
| 200 | - '直连设备' : | |
| 201 | - this.deviceDetail.deviceType === 'GATEWAY' ? | |
| 202 | - '网关设备' : | |
| 203 | - this.deviceDetail.deviceType === 'SENSOR' ? | |
| 204 | - '网关子设备' : | |
| 205 | - ''; | |
| 206 | - }, | |
| 207 | - alarmStatus() { | |
| 208 | - return this.deviceDetail.alarmStatus === '0' ? '否' : '是'; | |
| 209 | - }, | |
| 210 | - formatLastOnlineTime() { | |
| 211 | - return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss'); | |
| 212 | - } | |
| 213 | - }, | |
| 214 | - onLoad(e) { | |
| 215 | - // 隐藏原生的tabbar | |
| 216 | - uni.hideTabBar(); | |
| 217 | - }, | |
| 218 | - mounted() {}, | |
| 219 | - beforeCreate() { | |
| 220 | - this.modalName = null | |
| 221 | - }, | |
| 222 | - methods: { | |
| 223 | - handleCopy(value) { | |
| 224 | - uni.showModal({ | |
| 225 | - content: JSON.stringify(value), | |
| 226 | - confirmText: '复制内容', | |
| 227 | - showCancel:false, | |
| 228 | - success: () => { | |
| 229 | - uni.setClipboardData({ | |
| 230 | - data: JSON.stringify(value), | |
| 231 | - success: () => { | |
| 232 | - uni.showToast({ | |
| 233 | - title: '复制成功' | |
| 234 | - }) | |
| 235 | - } | |
| 236 | - }); | |
| 237 | - }, | |
| 238 | - | |
| 239 | - }); | |
| 240 | - }, | |
| 241 | - radioChange: function(evt) { | |
| 242 | - for (let i = 0; i < this.items.length; i++) { | |
| 243 | - if (this.items[i].value === evt.detail.value) { | |
| 244 | - this.current = i; | |
| 245 | - break; | |
| 246 | - } | |
| 247 | - } | |
| 248 | - this.commandType = evt.detail.value | |
| 249 | - }, | |
| 250 | - handleClick() { | |
| 251 | - const data = { | |
| 252 | - longitude: this.deviceDetail.deviceInfo.longitude || 0, | |
| 253 | - latitude: this.deviceDetail.deviceInfo.latitude || 0 | |
| 254 | - }; | |
| 255 | - uni.navigateTo({ | |
| 256 | - url: '/deviceSubPage/deviceDetailPage/devicePosition?data=' + JSON.stringify(data) | |
| 257 | - }); | |
| 258 | - }, | |
| 259 | - showModal(e) { | |
| 260 | - this.modalName = e.currentTarget.dataset.target | |
| 261 | - const {transportType} = this.deviceDetail.deviceProfile | |
| 262 | - this.isShowTCP = transportType=='TCP'?true:false | |
| 263 | - this.showNodal = true | |
| 264 | - }, | |
| 265 | - showModalBtn() { | |
| 266 | - this.showModel = true; | |
| 267 | - this.inputCommandVal = ''; | |
| 268 | - const {transportType} = this.deviceDetail.deviceProfile | |
| 269 | - this.isShowTCP = transportType=='TCP'?true:false | |
| 270 | - }, | |
| 271 | - disabledScroll() { | |
| 272 | - return; | |
| 273 | - }, | |
| 274 | - hiddenModal() { | |
| 275 | - this.showModel = false; | |
| 276 | - this.inputCommandVal = ''; | |
| 277 | - // #ifdef APP-PLUS | |
| 278 | - this.modalName = null | |
| 279 | - this.showNodal = false | |
| 280 | - // #endif | |
| 281 | - }, | |
| 282 | - async confirmCommand() { | |
| 283 | - try { | |
| 284 | - this.commandValue.method = 'methodThingskit'; | |
| 285 | - this.commandValue.persistent = true; | |
| 286 | - this.commandValue.additionalInfo = { | |
| 287 | - cmdType: 'API' | |
| 288 | - }; | |
| 289 | - if(this.isShowTCP){//TCP的格式只能是字符串 | |
| 290 | - const zg = /^[0-9a-zA-Z]*$/ | |
| 291 | - if(!zg.test(this.inputCommandVal)) { | |
| 292 | - uni.$u.toast('输入的内容只能是字母和数字的组合') | |
| 293 | - return | |
| 294 | - } | |
| 295 | - this.commandValue.params = this.inputCommandVal | |
| 296 | - }else{ | |
| 297 | - const commandJsonValue = JSON.parse(this.inputCommandVal); | |
| 298 | - this.commandValue.params = commandJsonValue | |
| 299 | - } | |
| 300 | - await issueCommand(this.commandType, this.deviceDetail.tbDeviceId, this.commandValue); | |
| 301 | - this.hiddenModal(); | |
| 302 | - uni.$u.toast('下发成功~'); | |
| 303 | - } catch (e) { | |
| 304 | - uni.$u.toast('下发失败~'); | |
| 305 | - } | |
| 306 | - }, | |
| 307 | - cancelCommand() { | |
| 308 | - this.hiddenModal(); | |
| 309 | - // #ifdef APP-PLUS | |
| 310 | - this.modalName = null | |
| 311 | - this.showNodal = false | |
| 312 | - // #endif | |
| 313 | - } | |
| 314 | - } | |
| 315 | - }; | |
| 316 | -</script> | |
| 317 | - | |
| 318 | -<style lang="scss" scoped> | |
| 319 | - @import url('../styles/modal.css'); | |
| 320 | - | |
| 321 | - .cusAppplusContent { | |
| 322 | - width: 625rpx; | |
| 323 | - height: 400rpx; | |
| 324 | - background: #FFFFFF; | |
| 325 | - box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.03); | |
| 326 | - border-radius: 10px; | |
| 327 | - | |
| 328 | - } | |
| 329 | - | |
| 330 | - .cusAppplusCancelBtn { | |
| 331 | - background: #e3e3e5; | |
| 332 | - border-radius: 38rpx; | |
| 333 | - height: 85rpx; | |
| 334 | - line-height: 85rpx | |
| 335 | - } | |
| 336 | - | |
| 337 | - .cusAppplusConfrimBtn { | |
| 338 | - background: #3388ff; | |
| 339 | - border-radius: 38rpx; | |
| 340 | - height: 85rpx; | |
| 341 | - line-height: 85rpx | |
| 342 | - } | |
| 343 | - | |
| 344 | - .cu-item { | |
| 345 | - background: #3388FF; | |
| 346 | - border-radius: 12px; | |
| 347 | - width: 120rpx; | |
| 348 | - height: 48rpx; | |
| 349 | - text-align: center; | |
| 350 | - line-height: 40rpx; | |
| 351 | - | |
| 352 | - text { | |
| 353 | - font-size: 12px; | |
| 354 | - font-family: PingFangSC-Regular, PingFang SC; | |
| 355 | - font-weight: 400; | |
| 356 | - color: #FFFFFF; | |
| 357 | - } | |
| 358 | - } | |
| 359 | - | |
| 360 | - | |
| 361 | - | |
| 362 | - .basic-page { | |
| 363 | - padding: 0 30rpx; | |
| 364 | - | |
| 365 | - .basic-title { | |
| 366 | - display: flex; | |
| 367 | - justify-content: space-between; | |
| 368 | - align-items: center; | |
| 369 | - height: 140rpx; | |
| 370 | - background-color: #fff; | |
| 371 | - border-radius: 20rpx; | |
| 372 | - } | |
| 373 | - | |
| 374 | - .detail { | |
| 375 | - background-color: #fff; | |
| 376 | - margin-top: 30rpx; | |
| 377 | - border-radius: 20rpx; | |
| 378 | - width: 690rpx; | |
| 379 | - | |
| 380 | - .detail-item { | |
| 381 | - padding: 30rpx; | |
| 382 | - display: flex; | |
| 383 | - align-items: center; | |
| 384 | - | |
| 385 | - .detail-label { | |
| 386 | - color: #333; | |
| 387 | - font-size: 15px; | |
| 388 | - } | |
| 389 | - | |
| 390 | - .detail-value { | |
| 391 | - color: #666; | |
| 392 | - font-size: 14px; | |
| 393 | - margin-left: 30rpx; | |
| 394 | - } | |
| 395 | - } | |
| 396 | - } | |
| 397 | - } | |
| 398 | - | |
| 399 | - /deep/ .u-modal__content { | |
| 400 | - padding: 30rpx 0 !important; | |
| 401 | - } | |
| 402 | - | |
| 403 | - .button-group { | |
| 404 | - display: flex; | |
| 405 | - margin-top: 40rpx; | |
| 406 | - justify-content: space-between; | |
| 407 | - | |
| 408 | - view { | |
| 409 | - width: 300rpx; | |
| 410 | - } | |
| 411 | - } | |
| 412 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="basic-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <!-- 基础信息头部 --> | |
| 6 | + <view class="basic-header"> | |
| 7 | + <view class="u-flex"> | |
| 8 | + <view class="pl-3"> | |
| 9 | + <u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick" | |
| 10 | + name="map-fill"></u-icon> | |
| 11 | + </view> | |
| 12 | + <view class="basic-text text-clip ml-2"> | |
| 13 | + {{ deviceDetail.alias ? deviceDetail.alias : deviceDetail.name }} | |
| 14 | + </view> | |
| 15 | + <view class="basic-text-status ml-2" :style="{ color: formatTextStatus(deviceDetail.deviceState) }"> | |
| 16 | + {{ deviceStatus }} | |
| 17 | + </view> | |
| 18 | + </view> | |
| 19 | + <!-- 命令下发 设备在线并且不是网关子设备 --> | |
| 20 | + <view class="mr-2" v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.deviceType !== 'SENSOR'"> | |
| 21 | + <!-- #ifdef MP --> | |
| 22 | + <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="handleMpShowModal" /> | |
| 23 | + <!-- #endif --> | |
| 24 | + <!-- #ifdef APP-PLUS --> | |
| 25 | + <view class="cu-item" @tap="handleAppShowModal" data-target="Modal"> | |
| 26 | + <text>下发命令</text> | |
| 27 | + </view> | |
| 28 | + <!-- #endif --> | |
| 29 | + </view> | |
| 30 | + </view> | |
| 31 | + <!-- 设备详情 --> | |
| 32 | + <view class="detail"> | |
| 33 | + <view class="detail-item"> | |
| 34 | + <view class="detail-label">设备编号</view> | |
| 35 | + <view class="detail-value">{{ deviceDetail.sn }}</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">{{ deviceType }}</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.organizationDTO.name }}</view> | |
| 46 | + </view> | |
| 47 | + <u-line length="90%" margin="0 auto"></u-line> | |
| 48 | + <view class="detail-item"> | |
| 49 | + <view class="detail-label">最后连接时间</view> | |
| 50 | + <view class="detail-value">{{ formatLastOnlineTime }}</view> | |
| 51 | + </view> | |
| 52 | + <u-line length="90%" margin="0 auto"></u-line> | |
| 53 | + <view class="detail-item"> | |
| 54 | + <view class="detail-label">是否告警</view> | |
| 55 | + <view class="detail-value">{{ alarmStatus }}</view> | |
| 56 | + </view> | |
| 57 | + <u-line length="90%" margin="0 auto"></u-line> | |
| 58 | + <view class="detail-item"> | |
| 59 | + <view class="detail-label">设备描述</view> | |
| 60 | + <view class="detail-value">{{ deviceDetail.description }}</view> | |
| 61 | + </view> | |
| 62 | + </view> | |
| 63 | + <!-- 命令下发 --> | |
| 64 | + <!-- #ifdef APP-PLUS --> | |
| 65 | + <!-- 原生弹窗 封装成子组件无效 --> | |
| 66 | + <view v-show="showNativeModal" class="cu-modal" :class="modalName == 'Modal' ? 'show' : ''"> | |
| 67 | + <view class="cu-dialog"> | |
| 68 | + <view class="app-command-content"> | |
| 69 | + <view class="app-command-text"> | |
| 70 | + <text>命令下发</text> | |
| 71 | + </view> | |
| 72 | + <view class="app-command-type"> | |
| 73 | + <text>下发类型</text> | |
| 74 | + <view class="mr-2"> | |
| 75 | + <radio-group @change="radioChange" class="flex mr-1"> | |
| 76 | + <label v-for="(item, index) in commandTypeList" :key="item.value"> | |
| 77 | + <view class="flex"> | |
| 78 | + <view class="ml-1"> | |
| 79 | + <radio :value="item.value" :checked="index === current" /> | |
| 80 | + </view> | |
| 81 | + <view style="width:10rpx"></view> | |
| 82 | + <view class="ml-1">{{item.name}}</view> | |
| 83 | + </view> | |
| 84 | + </label> | |
| 85 | + </radio-group> | |
| 86 | + </view> | |
| 87 | + </view> | |
| 88 | + <view class="app-command-body"> | |
| 89 | + <textarea class="app-command-textarea" v-model="inputCommandContent" | |
| 90 | + :placeholder="`请输入下发内容${isShowTCP?'(字符串格式)':'(json格式)'}`" /> | |
| 91 | + <u-icon @click="handleCopy(copyTextValue)" v-if="!isShowTCP" name="question-circle" | |
| 92 | + color="#2979ff" size="28" class="ml-10"> | |
| 93 | + </u-icon> | |
| 94 | + </view> | |
| 95 | + <view class="app-command-buttons"> | |
| 96 | + <view class="cancel-button" @click="cancelCommand"><text class="cancel-text">取消</text></view> | |
| 97 | + <view @click="handleAppCommand" class="confrim-button"><text class="confrim-text">确认</text> | |
| 98 | + </view> | |
| 99 | + </view> | |
| 100 | + </view> | |
| 101 | + </view> | |
| 102 | + </view> | |
| 103 | + <!-- #endif --> | |
| 104 | + <!-- #ifdef MP --> | |
| 105 | + <!-- u-modal在app端弹窗层级无法覆盖背景色 --> | |
| 106 | + <mp-command-issuance ref="mpCommandIssuanceRef" :isShowTCP="isShowTCP" :showModal="mpShowModal" | |
| 107 | + @hideModal="hideMpModal" @cancelCommand="cancelCommand" | |
| 108 | + @confirmCommand="confirmCommand"></mp-command-issuance> | |
| 109 | + <!-- #endif --> | |
| 110 | + </view> | |
| 111 | +</template> | |
| 112 | + | |
| 113 | +<script> | |
| 114 | + import {formatToDate} from '@/plugins/utils.js'; | |
| 115 | + import {issueCommand} from '../api/index.js'; | |
| 116 | + import api from '@/api/index.js'; | |
| 117 | + import mpCommandIssuance from './mp-command-issuance.vue'; | |
| 118 | + import {commandTypeList} from '../config/data.js' | |
| 119 | + import {useShowModal} from '@/plugins/utils.js' | |
| 120 | + | |
| 121 | + export default { | |
| 122 | + components: { | |
| 123 | + mpCommandIssuance, | |
| 124 | + }, | |
| 125 | + props: { | |
| 126 | + deviceDetail: { | |
| 127 | + type: Object, | |
| 128 | + default: () => ({}) | |
| 129 | + } | |
| 130 | + }, | |
| 131 | + data() { | |
| 132 | + return { | |
| 133 | + showNativeModal: false, | |
| 134 | + current: 0, | |
| 135 | + commandTypeList, | |
| 136 | + commandTypeStr: 'OneWay', | |
| 137 | + inputCommandContent: '', | |
| 138 | + mpShowModal: false, | |
| 139 | + commandValue: {}, | |
| 140 | + isShowTCP: false, //用于下发命令时判断是否是TCP/UDP | |
| 141 | + modalName: null, | |
| 142 | + copyTextValue: { | |
| 143 | + "method": "methodThingskit", | |
| 144 | + "params": { | |
| 145 | + "pin": 7, | |
| 146 | + "value": 1 | |
| 147 | + } | |
| 148 | + } | |
| 149 | + }; | |
| 150 | + }, | |
| 151 | + computed: { | |
| 152 | + deviceStatus() { | |
| 153 | + return this.deviceDetail.deviceState === 'INACTIVE' ? '待激活' : this.deviceDetail.deviceState === 'ONLINE' ? | |
| 154 | + '在线' : '离线'; | |
| 155 | + }, | |
| 156 | + deviceType() { | |
| 157 | + return this.deviceDetail.deviceType === 'DIRECT_CONNECTION' ? | |
| 158 | + '直连设备' : | |
| 159 | + this.deviceDetail.deviceType === 'GATEWAY' ? | |
| 160 | + '网关设备' : | |
| 161 | + this.deviceDetail.deviceType === 'SENSOR' ? | |
| 162 | + '网关子设备' : | |
| 163 | + ''; | |
| 164 | + }, | |
| 165 | + alarmStatus() { | |
| 166 | + return this.deviceDetail.alarmStatus === '0' ? '否' : '是'; | |
| 167 | + }, | |
| 168 | + formatLastOnlineTime() { | |
| 169 | + return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss'); | |
| 170 | + } | |
| 171 | + }, | |
| 172 | + beforeCreate() { | |
| 173 | + this.modalName = null | |
| 174 | + }, | |
| 175 | + onLoad() { | |
| 176 | + // 隐藏原生的tabbar | |
| 177 | + uni.hideTabBar(); | |
| 178 | + this.modalName = null | |
| 179 | + }, | |
| 180 | + methods: { | |
| 181 | + handleCopy(value) { | |
| 182 | + useShowModal(JSON.stringify(value), '命令下发', '复制内容').then(res => { | |
| 183 | + uni.setClipboardData({ | |
| 184 | + data: JSON.stringify(value), | |
| 185 | + success: () => { | |
| 186 | + uni.showToast({ | |
| 187 | + title: '复制成功' | |
| 188 | + }) | |
| 189 | + } | |
| 190 | + }); | |
| 191 | + }) | |
| 192 | + }, | |
| 193 | + radioChange: function(evt) { | |
| 194 | + for (let i = 0; i < this.commandTypeList.length; i++) { | |
| 195 | + if (this.items[i].value === evt.detail.value) { | |
| 196 | + this.current = i; | |
| 197 | + break; | |
| 198 | + } | |
| 199 | + } | |
| 200 | + this.commandTypeStr = evt.detail.value | |
| 201 | + }, | |
| 202 | + formatTextStatus(deviceState) { | |
| 203 | + return deviceState === 'INACTIVE' ? '#666' : deviceState === 'ONLINE' ? '#377DFF' : '#DE4437'; | |
| 204 | + }, | |
| 205 | + handleClick() { | |
| 206 | + const data = { | |
| 207 | + longitude: this.deviceDetail.deviceInfo.longitude || 0, | |
| 208 | + latitude: this.deviceDetail.deviceInfo.latitude || 0 | |
| 209 | + }; | |
| 210 | + uni.navigateTo({ | |
| 211 | + url: '/device-subpackage/device-detail/device-position?data=' + JSON.stringify(data) | |
| 212 | + }); | |
| 213 | + }, | |
| 214 | + disabledScroll() { | |
| 215 | + return; | |
| 216 | + }, | |
| 217 | + handleAppShowModal(e) { | |
| 218 | + this.modalName = e.currentTarget.dataset.target; | |
| 219 | + this.showNativeModal = true | |
| 220 | + }, | |
| 221 | + handleMpShowModal() { | |
| 222 | + const { | |
| 223 | + transportType | |
| 224 | + } = this.deviceDetail.deviceProfile; | |
| 225 | + this.isShowTCP = transportType == 'TCP' ? true : false; | |
| 226 | + this.mpShowModal = true; | |
| 227 | + }, | |
| 228 | + hideMpModal() { | |
| 229 | + this.mpShowModal = false; | |
| 230 | + }, | |
| 231 | + hideAppModal() { | |
| 232 | + this.modalName = null; | |
| 233 | + this.showNativeModal = false | |
| 234 | + }, | |
| 235 | + confirmCommand(commandType, inputCommandVal) { | |
| 236 | + this.handleCommand(commandType, inputCommandVal) | |
| 237 | + }, | |
| 238 | + cancelCommand() { | |
| 239 | + this.hideMpModal(); | |
| 240 | + this.hideAppModal(); | |
| 241 | + this.commandTypeStr = 'OneWay' | |
| 242 | + this.inputCommandContent = '' | |
| 243 | + this.$nextTick(() => { | |
| 244 | + this.$refs.mpCommandIssuanceRef.reset() | |
| 245 | + }) | |
| 246 | + }, | |
| 247 | + handleAppCommand() { | |
| 248 | + this.handleCommand(this.commandTypeStr, this.inputCommandContent) | |
| 249 | + }, | |
| 250 | + async handleCommand(commandType, inputCommandVal) { | |
| 251 | + if (!inputCommandVal) return uni.$u.toast('请输入下发内容~'); | |
| 252 | + if (this.isShowTCP) { | |
| 253 | + //TCP的格式只能是字符串 | |
| 254 | + const zg = /^[0-9a-zA-Z]*$/; | |
| 255 | + if (!zg.test(inputCommandVal)) { | |
| 256 | + uni.$u.toast('输入的内容只能是字母和数字的组合'); | |
| 257 | + return; | |
| 258 | + } | |
| 259 | + this.commandValue.params = inputCommandVal; | |
| 260 | + } else { | |
| 261 | + this.commandValue.params = JSON.parse(inputCommandVal); | |
| 262 | + } | |
| 263 | + this.commandValue.persistent = true; | |
| 264 | + this.commandValue.additionalInfo = { | |
| 265 | + cmdType: 'API' | |
| 266 | + }; | |
| 267 | + this.commandValue.method = 'methodThingskit'; | |
| 268 | + this.commandValue.params = inputCommandVal; | |
| 269 | + await api.deviceApi.issueCommand(commandType, this.deviceDetail.tbDeviceId, this.commandValue); | |
| 270 | + this.cancelCommand(); | |
| 271 | + uni.$u.toast('下发成功~'); | |
| 272 | + | |
| 273 | + }, | |
| 274 | + | |
| 275 | + } | |
| 276 | + }; | |
| 277 | +</script> | |
| 278 | + | |
| 279 | +<style lang="scss" scoped> | |
| 280 | + @import url('../static/modal.css'); | |
| 281 | + | |
| 282 | + .app-command-content { | |
| 283 | + .app-command-text { | |
| 284 | + display: flex; | |
| 285 | + justify-content: center; | |
| 286 | + align-items: center; | |
| 287 | + | |
| 288 | + text { | |
| 289 | + font-weight: 700; | |
| 290 | + } | |
| 291 | + } | |
| 292 | + | |
| 293 | + .app-command-type { | |
| 294 | + display: flex; | |
| 295 | + margin-top: 20rpx; | |
| 296 | + margin-left: 20rpx; | |
| 297 | + | |
| 298 | + text { | |
| 299 | + font-weight: 700; | |
| 300 | + } | |
| 301 | + } | |
| 302 | + | |
| 303 | + .app-command-body { | |
| 304 | + display: flex; | |
| 305 | + align-items: center; | |
| 306 | + justify-content: space-between; | |
| 307 | + margin-top: 20rpx; | |
| 308 | + margin-left: 20rpx; | |
| 309 | + | |
| 310 | + .app-command-textarea { | |
| 311 | + width: 625rpx; | |
| 312 | + height: 400rpx; | |
| 313 | + background: #FFFFFF; | |
| 314 | + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.03); | |
| 315 | + border-radius: 10px; | |
| 316 | + } | |
| 317 | + } | |
| 318 | + | |
| 319 | + .app-command-buttons { | |
| 320 | + display: flex; | |
| 321 | + align-items: center; | |
| 322 | + justify-content: space-evenly; | |
| 323 | + height: 85rpx; | |
| 324 | + margin-top: 20rpx; | |
| 325 | + margin-bottom: 20rpx; | |
| 326 | + | |
| 327 | + .cancel-button { | |
| 328 | + width: 300rpx; | |
| 329 | + background: #e3e3e5; | |
| 330 | + height: 85rpx; | |
| 331 | + border-radius: 38rpx; | |
| 332 | + line-height: 85rpx; | |
| 333 | + | |
| 334 | + .cancel-text { | |
| 335 | + color: #333333 | |
| 336 | + } | |
| 337 | + } | |
| 338 | + | |
| 339 | + .confrim-button { | |
| 340 | + width: 300rpx; | |
| 341 | + background: #3388ff; | |
| 342 | + border-radius: 38rpx; | |
| 343 | + height: 85rpx; | |
| 344 | + line-height: 85rpx; | |
| 345 | + | |
| 346 | + .confrim-text { | |
| 347 | + color: white | |
| 348 | + } | |
| 349 | + } | |
| 350 | + } | |
| 351 | + } | |
| 352 | + | |
| 353 | + .basic-page { | |
| 354 | + padding: 0 30rpx; | |
| 355 | + | |
| 356 | + .basic-header { | |
| 357 | + display: flex; | |
| 358 | + justify-content: space-between; | |
| 359 | + align-items: center; | |
| 360 | + height: 140rpx; | |
| 361 | + background-color: #fff; | |
| 362 | + border-radius: 20rpx; | |
| 363 | + | |
| 364 | + .basic-text { | |
| 365 | + width: 370rpx; | |
| 366 | + } | |
| 367 | + | |
| 368 | + .cu-item { | |
| 369 | + background: #3388ff; | |
| 370 | + border-radius: 12px; | |
| 371 | + width: 120rpx; | |
| 372 | + height: 48rpx; | |
| 373 | + text-align: center; | |
| 374 | + line-height: 40rpx; | |
| 375 | + | |
| 376 | + text { | |
| 377 | + font-size: 12px; | |
| 378 | + font-family: PingFangSC-Regular, PingFang SC; | |
| 379 | + font-weight: 400; | |
| 380 | + color: #ffffff; | |
| 381 | + } | |
| 382 | + } | |
| 383 | + | |
| 384 | + .basic-text-status { | |
| 385 | + font-size: 14px; | |
| 386 | + } | |
| 387 | + } | |
| 388 | + | |
| 389 | + .detail { | |
| 390 | + background-color: #fff; | |
| 391 | + margin-top: 30rpx; | |
| 392 | + border-radius: 20rpx; | |
| 393 | + width: 690rpx; | |
| 394 | + | |
| 395 | + .detail-item { | |
| 396 | + padding: 30rpx; | |
| 397 | + display: flex; | |
| 398 | + align-items: center; | |
| 399 | + | |
| 400 | + .detail-label { | |
| 401 | + color: #333; | |
| 402 | + font-size: 15px; | |
| 403 | + } | |
| 404 | + | |
| 405 | + .detail-value { | |
| 406 | + color: #666; | |
| 407 | + font-size: 14px; | |
| 408 | + margin-left: 30rpx; | |
| 409 | + } | |
| 410 | + } | |
| 411 | + } | |
| 412 | + } | |
| 413 | + | |
| 414 | + /deep/ .u-modal__content { | |
| 415 | + padding: 30rpx 0 !important; | |
| 416 | + } | |
| 417 | +</style> | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/components/command-detail.vue
renamed from
deviceSubPage/deviceDetailPage/tabDetail/CommandDetail.vue
| 1 | -<template> | |
| 2 | - <view class="command-detail"> | |
| 3 | - <view class="detail-top">{{ commandDetail.deviceName }}</view> | |
| 4 | - <view class="detail"> | |
| 5 | - <view class="detail-item"> | |
| 6 | - <view class="detail-label">设备类型</view> | |
| 7 | - <view class="detail-value">{{ deviceType }}</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">{{ commandDetail.deviceSn }}</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">{{ commandDetail.organizationName }}</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">{{ format(commandDetail.createTime) }}</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">{{ commandDetail.additionalInfo.cmdType===1?'服务':'自定义' }}</view> | |
| 28 | - </view> | |
| 29 | - <u-line length="90%" margin="0 auto" v-if="commandDetail.additionalInfo.cmdType"></u-line> | |
| 30 | - <view class="detail-item"> | |
| 31 | - <view class="detail-label">响应类型</view> | |
| 32 | - <view class="detail-value">{{ commandDetail.request.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">{{ commandDetail.statusName }}</view> | |
| 38 | - </view> | |
| 39 | - <u-line length="90%" margin="0 auto"></u-line> | |
| 40 | - <view class="detail-item" v-if="!commandDetail.request.oneway"> | |
| 41 | - <view class="detail-label">响应结果</view> | |
| 42 | - <view class="detail-value">{{ commandDetail.response?JSON.stringify(commandDetail.response):'无' }}</view> | |
| 43 | - </view> | |
| 44 | - <!-- <view class="detail-item" v-if="!commandDetail.request.oneway"> | |
| 45 | - <view class="detail-label">响应失败内容</view> | |
| 46 | - <view class="detail-value" style="width: 400rpx;" v-if="commandDetail.response.status!=='SUCCESS'"> | |
| 47 | - <u--textarea placeholder="响应失败内容" v-model="failContent" /> | |
| 48 | - </view> | |
| 49 | - </view> --> | |
| 50 | - </view> | |
| 51 | - <view class="command">命令内容</view> | |
| 52 | - <u-textarea :value="formatValue(commandDetail.request.body)" disabled></u-textarea> | |
| 53 | - <view style="height: 50rpx;"></view> | |
| 54 | - </view> | |
| 55 | -</template> | |
| 56 | - | |
| 57 | -<script> | |
| 58 | - import { | |
| 59 | - formatToDate | |
| 60 | - } from '@/plugins/utils.js'; | |
| 61 | - export default { | |
| 62 | - data() { | |
| 63 | - return { | |
| 64 | - commandDetail: {}, | |
| 65 | - failContent: "" | |
| 66 | - }; | |
| 67 | - }, | |
| 68 | - computed: { | |
| 69 | - deviceType() { | |
| 70 | - return this.commandDetail.deviceType === 'DIRECT_CONNECTION' ? | |
| 71 | - '直连设备' : | |
| 72 | - this.commandDetail.deviceType === 'GATEWAY' ? | |
| 73 | - '网关设备' : | |
| 74 | - this.commandDetail.deviceType === 'SENSOR' ? | |
| 75 | - '网关子设备' : | |
| 76 | - ''; | |
| 77 | - } | |
| 78 | - }, | |
| 79 | - methods: { | |
| 80 | - format(date) { | |
| 81 | - return formatToDate(date, 'YYYY-MM-DD HH:mm:ss'); | |
| 82 | - }, | |
| 83 | - formatValue(value) { | |
| 84 | - try { | |
| 85 | - const val = JSON.parse(value['params']); | |
| 86 | - //微信小程序端object无法显示,格式化为字符串 | |
| 87 | - const stringifyVal = JSON.stringify(val['params']) | |
| 88 | - const formatVal = stringifyVal | |
| 89 | - .replace(/\\"/g, '"') | |
| 90 | - .replace(/]"/g, ']') | |
| 91 | - .replace(/"\[/g, '['); | |
| 92 | - return formatVal | |
| 93 | - } catch (e) { | |
| 94 | - console.error("命令记录页面格式化无返回值", e); | |
| 95 | - return value['params'] | |
| 96 | - } | |
| 97 | - } | |
| 98 | - }, | |
| 99 | - onLoad(options) { | |
| 100 | - const { | |
| 101 | - data | |
| 102 | - } = options; | |
| 103 | - this.commandDetail = JSON.parse(data); | |
| 104 | - if (this.commandDetail.response.status === 'SUCCESS') return | |
| 105 | - this.failContent = JSON.stringify(this.commandDetail.response.error) | |
| 106 | - } | |
| 107 | - }; | |
| 108 | -</script> | |
| 109 | - | |
| 110 | -<style lang="scss" scoped> | |
| 111 | - .command-detail { | |
| 112 | - padding: 0 30rpx; | |
| 113 | - height: 100vh; | |
| 114 | - background-color: #f8f9fa; | |
| 115 | - | |
| 116 | - .detail-top { | |
| 117 | - height: 118rpx; | |
| 118 | - width: 690rpx; | |
| 119 | - display: flex; | |
| 120 | - align-items: center; | |
| 121 | - background-color: #fff; | |
| 122 | - color: #333; | |
| 123 | - border-radius: 20rpx; | |
| 124 | - font-size: 15px; | |
| 125 | - margin-top: 30rpx; | |
| 126 | - padding: 30rpx; | |
| 127 | - } | |
| 128 | - | |
| 129 | - .detail { | |
| 130 | - background-color: #fff; | |
| 131 | - margin-top: 30rpx; | |
| 132 | - border-radius: 20rpx; | |
| 133 | - width: 690rpx; | |
| 134 | - | |
| 135 | - .detail-item { | |
| 136 | - padding: 30rpx; | |
| 137 | - display: flex; | |
| 138 | - align-items: center; | |
| 139 | - | |
| 140 | - .detail-label { | |
| 141 | - color: #333; | |
| 142 | - font-size: 15px; | |
| 143 | - } | |
| 144 | - | |
| 145 | - .detail-value { | |
| 146 | - color: #666; | |
| 147 | - font-size: 14px; | |
| 148 | - margin-left: 30rpx; | |
| 149 | - } | |
| 150 | - } | |
| 151 | - } | |
| 152 | - | |
| 153 | - .command { | |
| 154 | - margin: 30rpx 0; | |
| 155 | - } | |
| 156 | - } | |
| 157 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="command-detail"> | |
| 3 | + <view class="detail-top">{{ commandDetail.deviceName }}</view> | |
| 4 | + <view class="detail"> | |
| 5 | + <view class="detail-item"> | |
| 6 | + <view class="detail-label">设备类型</view> | |
| 7 | + <view class="detail-value">{{ deviceType }}</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">{{ commandDetail.deviceSn }}</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">{{ commandDetail.organizationName }}</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">{{ format(commandDetail.createTime) }}</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">{{ commandDetail.additionalInfo.cmdType===1?'服务':'自定义' }}</view> | |
| 28 | + </view> | |
| 29 | + <u-line length="90%" margin="0 auto" v-if="commandDetail.additionalInfo.cmdType"></u-line> | |
| 30 | + <view class="detail-item"> | |
| 31 | + <view class="detail-label">响应类型</view> | |
| 32 | + <view class="detail-value">{{ commandDetail.request.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">{{ commandDetail.statusName }}</view> | |
| 38 | + </view> | |
| 39 | + <u-line length="90%" margin="0 auto"></u-line> | |
| 40 | + <view class="detail-item" v-if="!commandDetail.request.oneway"> | |
| 41 | + <view class="detail-label">响应结果</view> | |
| 42 | + <view class="detail-value">{{ commandDetail.response?JSON.stringify(commandDetail.response):'无' }} | |
| 43 | + </view> | |
| 44 | + </view> | |
| 45 | + </view> | |
| 46 | + <view class="command">命令内容</view> | |
| 47 | + <u-textarea :value="formatValue(commandDetail.request.body)" disabled></u-textarea> | |
| 48 | + <view style="height: 50rpx;"></view> | |
| 49 | + </view> | |
| 50 | +</template> | |
| 51 | + | |
| 52 | +<script> | |
| 53 | + import { | |
| 54 | + formatToDate | |
| 55 | + } from '@/plugins/utils.js'; | |
| 56 | + export default { | |
| 57 | + data() { | |
| 58 | + return { | |
| 59 | + commandDetail: {}, | |
| 60 | + failContent: "" | |
| 61 | + }; | |
| 62 | + }, | |
| 63 | + computed: { | |
| 64 | + deviceType() { | |
| 65 | + return this.commandDetail.deviceType === 'DIRECT_CONNECTION' ? | |
| 66 | + '直连设备' : | |
| 67 | + this.commandDetail.deviceType === 'GATEWAY' ? | |
| 68 | + '网关设备' : | |
| 69 | + this.commandDetail.deviceType === 'SENSOR' ? | |
| 70 | + '网关子设备' : | |
| 71 | + ''; | |
| 72 | + } | |
| 73 | + }, | |
| 74 | + methods: { | |
| 75 | + format(date) { | |
| 76 | + return formatToDate(date, 'YYYY-MM-DD HH:mm:ss'); | |
| 77 | + }, | |
| 78 | + formatValue(value) { | |
| 79 | + try { | |
| 80 | + const val = JSON.parse(value['params']); | |
| 81 | + //微信小程序端object无法显示,格式化为字符串 | |
| 82 | + const stringifyVal = JSON.stringify(val['params']) | |
| 83 | + const formatVal = stringifyVal | |
| 84 | + .replace(/\\"/g, '"') | |
| 85 | + .replace(/]"/g, ']') | |
| 86 | + .replace(/"\[/g, '['); | |
| 87 | + return formatVal | |
| 88 | + } catch (e) { | |
| 89 | + return value['params'] | |
| 90 | + } | |
| 91 | + } | |
| 92 | + }, | |
| 93 | + onLoad(options) { | |
| 94 | + const { data } = options; | |
| 95 | + this.commandDetail = JSON.parse(decodeURIComponent(data)); | |
| 96 | + if (this.commandDetail.response.status === 'SUCCESS') return | |
| 97 | + this.failContent = JSON.stringify(this.commandDetail.response.error) | |
| 98 | + } | |
| 99 | + }; | |
| 100 | +</script> | |
| 101 | + | |
| 102 | +<style lang="scss" scoped> | |
| 103 | + @import "../static/command-detail.scss"; | |
| 104 | +</style> | |
| \ No newline at end of file | ... | ... |
| 1 | +<template> | |
| 2 | + <view class="command-record"> | |
| 3 | + <!-- 命令记录筛选--> | |
| 4 | + <view class="filter-button" @click="openSearchDialog"> | |
| 5 | + <text>筛选</text> | |
| 6 | + <image src="/static/shaixuan.png" /> | |
| 7 | + </view> | |
| 8 | + <!-- 命令记录分页 --> | |
| 9 | + <mescroll-uni ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback" | |
| 10 | + height="700px"> | |
| 11 | + <view @click="openCommandDetail(item)" class="list-item" v-for="(item, index) in list" :key="index"> | |
| 12 | + <view class="item"> | |
| 13 | + <view class="item-first"> | |
| 14 | + <text>{{ item.deviceName }}</text> | |
| 15 | + <!-- 业务 单向是没有响应状态 --> | |
| 16 | + <view v-if="!item.request.oneway"> | |
| 17 | + <view class="item-right item-success" v-if="item.response">响应成功</view> | |
| 18 | + <view class="item-right item-fail" v-else>响应失败</view> | |
| 19 | + </view> | |
| 20 | + </view> | |
| 21 | + <view> | |
| 22 | + 命令类型: | |
| 23 | + <text class="ml-16">{{ item.additionalInfo.cmdType===1?'服务':'自定义' }}</text> | |
| 24 | + </view> | |
| 25 | + <view v-if="item.statusName"> | |
| 26 | + 命令状态: | |
| 27 | + <text :style="{color:formatCommandStatus(item.status)}" class="ml-16"> | |
| 28 | + {{ item.statusName }} | |
| 29 | + </text> | |
| 30 | + </view> | |
| 31 | + <view class="item-first"> | |
| 32 | + <view> | |
| 33 | + 响应类型: | |
| 34 | + <text class="ml-16">{{ !item.request.oneway?'双向':'单向' }}</text> | |
| 35 | + </view> | |
| 36 | + <view class="time">{{ format(item.createTime) }}</view> | |
| 37 | + </view> | |
| 38 | + </view> | |
| 39 | + </view> | |
| 40 | + </mescroll-uni> | |
| 41 | + <!-- 命令记录弹窗筛选 --> | |
| 42 | + <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20"> | |
| 43 | + <view class="filter" @touchmove.stop.prevent="disabledScroll"> | |
| 44 | + <view class="filter-title"><text>筛选条件</text></view> | |
| 45 | + <query-item :filterList="issueStatus" title="下发状态" | |
| 46 | + @clickTag="currentIndex => handleClickTag(currentIndex, issueStatus)"></query-item> | |
| 47 | + <view class="flex-column"> | |
| 48 | + <view class="mt-3 command-time-text">命令下发时间</view> | |
| 49 | + <view class="mt-3"> | |
| 50 | + <uni-datetime-picker return-type="timestamp" v-model="range" type="datetimerange" | |
| 51 | + rangeSeparator="至" /> | |
| 52 | + </view> | |
| 53 | + </view> | |
| 54 | + <view class="h-30"></view> | |
| 55 | + <view class="button-group"> | |
| 56 | + <view> | |
| 57 | + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" | |
| 58 | + @click="resetFilter"></u-button> | |
| 59 | + </view> | |
| 60 | + <view> | |
| 61 | + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button> | |
| 62 | + </view> | |
| 63 | + </view> | |
| 64 | + </view> | |
| 65 | + </u-popup> | |
| 66 | + </view> | |
| 67 | +</template> | |
| 68 | +<script> | |
| 69 | + import queryItem from '@/pages/device/components/query-item.vue'; | |
| 70 | + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 71 | + import { | |
| 72 | + formatToDate | |
| 73 | + } from '@/plugins/utils.js'; | |
| 74 | + import { | |
| 75 | + debounce | |
| 76 | + } from '@/plugins/throttle.js'; | |
| 77 | + import { | |
| 78 | + issueStatus | |
| 79 | + } from '../config/data.js' | |
| 80 | + import api from '@/api/index.js' | |
| 81 | + import { | |
| 82 | + useNavigateTo | |
| 83 | + } from '@/plugins/utils.js' | |
| 84 | + | |
| 85 | + export default { | |
| 86 | + mixins: [MescrollMixin], | |
| 87 | + components: { | |
| 88 | + queryItem | |
| 89 | + }, | |
| 90 | + props: { | |
| 91 | + tbDeviceId: { | |
| 92 | + type: String, | |
| 93 | + default: '' | |
| 94 | + } | |
| 95 | + }, | |
| 96 | + data() { | |
| 97 | + return { | |
| 98 | + show: false, | |
| 99 | + list: [], | |
| 100 | + total: 0, | |
| 101 | + range: [], | |
| 102 | + formTime: { | |
| 103 | + status: '', | |
| 104 | + startTime: '', | |
| 105 | + endTime: '' | |
| 106 | + }, | |
| 107 | + status: '', | |
| 108 | + issueStatus, | |
| 109 | + downOption: { | |
| 110 | + auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 111 | + }, | |
| 112 | + page: { | |
| 113 | + num: 0, | |
| 114 | + size: 10 | |
| 115 | + } | |
| 116 | + }; | |
| 117 | + }, | |
| 118 | + methods: { | |
| 119 | + formatCommandStatus(status) { | |
| 120 | + return status == 'EXPIRED' ? | |
| 121 | + 'red' : | |
| 122 | + status == 'DELIVERED' ? | |
| 123 | + 'blue' : | |
| 124 | + status == 'QUEUED' ? | |
| 125 | + '#00C9A7' : | |
| 126 | + status == 'TIMEOUT' ? | |
| 127 | + 'red' : | |
| 128 | + status == 'SENT' ? | |
| 129 | + '#00C9A7' : '' | |
| 130 | + }, | |
| 131 | + downCallback() { | |
| 132 | + for (let i in this.formTime) Reflect.set(this.formTime, i, '') | |
| 133 | + this.list = []; | |
| 134 | + this.page.num = 1; | |
| 135 | + this.loadData(this.page.num, { | |
| 136 | + tbDeviceId: this.tbDeviceId | |
| 137 | + }); | |
| 138 | + }, | |
| 139 | + format(date) { | |
| 140 | + return formatToDate(date, 'YYYY-MM-DD HH:mm:ss'); | |
| 141 | + }, | |
| 142 | + disabledScroll() { | |
| 143 | + return; | |
| 144 | + }, | |
| 145 | + upCallback() { | |
| 146 | + const tbDeviceId = { | |
| 147 | + tbDeviceId: this.tbDeviceId | |
| 148 | + } | |
| 149 | + const condition = Object.values(this.formTime) | |
| 150 | + if (condition.length === 0) { | |
| 151 | + this.page.num += 1; | |
| 152 | + this.loadData(this.page.num, { | |
| 153 | + ...tbDeviceId | |
| 154 | + }); | |
| 155 | + } else if (condition.filter(Boolean).length > 0) { | |
| 156 | + this.page.num += 1; | |
| 157 | + this.loadData(this.page.num, { | |
| 158 | + ...this.formTime, | |
| 159 | + ...tbDeviceId | |
| 160 | + }); | |
| 161 | + } else { | |
| 162 | + this.page.num += 1; | |
| 163 | + this.loadData(this.page.num, { | |
| 164 | + ...tbDeviceId | |
| 165 | + }); | |
| 166 | + } | |
| 167 | + }, | |
| 168 | + async loadData(pageNo, params = {}) { | |
| 169 | + let httpData = { | |
| 170 | + ...params, | |
| 171 | + page: pageNo, | |
| 172 | + pageSize: 10 | |
| 173 | + }; | |
| 174 | + const res = await api.deviceApi.getRpcRecord({ | |
| 175 | + params: httpData, | |
| 176 | + custom: { | |
| 177 | + load: false | |
| 178 | + } | |
| 179 | + }) | |
| 180 | + if (!res) return | |
| 181 | + this.total = res.total; | |
| 182 | + uni.stopPullDownRefresh(); | |
| 183 | + this.mescroll.endByPage(res.items.length, res.total); | |
| 184 | + if (pageNo == 1) { | |
| 185 | + this.list = res.items; | |
| 186 | + } else { | |
| 187 | + this.list = this.list.concat(res.items); | |
| 188 | + } | |
| 189 | + }, | |
| 190 | + handleClickTag(currentIndex, list) { | |
| 191 | + list.map((item, index) => { | |
| 192 | + item.checked = index === currentIndex; | |
| 193 | + }); | |
| 194 | + }, | |
| 195 | + resetFilter() { | |
| 196 | + const { | |
| 197 | + issueStatus | |
| 198 | + } = this; | |
| 199 | + issueStatus.forEach(item => item.checked = false) | |
| 200 | + issueStatus[0].checked = true | |
| 201 | + }, | |
| 202 | + close() { | |
| 203 | + this.show = false; | |
| 204 | + }, | |
| 205 | + openSearchDialog() { | |
| 206 | + this.show = true; | |
| 207 | + this.resetFilter() | |
| 208 | + this.range = [] | |
| 209 | + for (let i in this.formTime) Reflect.set(this.formTime, i, '') | |
| 210 | + }, | |
| 211 | + hideKeyboard() { | |
| 212 | + uni.hideKeyboard(); | |
| 213 | + }, | |
| 214 | + confirmFilter() { | |
| 215 | + this.formTime.startTime = this.range[0] | |
| 216 | + this.formTime.endTime = this.range[1] | |
| 217 | + const issueStatus = this.issueStatus.find(item => item.checked); | |
| 218 | + this.formTime.status = issueStatus.type ? issueStatus.type : undefined, | |
| 219 | + this.loadData(1, { | |
| 220 | + tbDeviceId: this.tbDeviceId, | |
| 221 | + ...this.formTime | |
| 222 | + }); | |
| 223 | + this.show = false; | |
| 224 | + }, | |
| 225 | + openCommandDetail(item) { | |
| 226 | + useNavigateTo('/device-subpackage/device-detail/components/command-detail?data=', item) | |
| 227 | + } | |
| 228 | + } | |
| 229 | + }; | |
| 230 | +</script> | |
| 231 | + | |
| 232 | + | |
| 233 | +<style lang="scss" scoped> | |
| 234 | + @import "../static/command-record.scss"; | |
| 235 | +</style> | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/components/history-data.vue
renamed from
deviceSubPage/deviceDetailPage/tabDetail/historyData.vue
| 1 | -<template> | |
| 2 | - <view class="historyData"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view class="historyData-top"> | |
| 6 | - <u-form :label-style="{ 'font-size': '0rpx' }"> | |
| 7 | - <u-form-item @click="openCalendar"> | |
| 8 | - <u-input v-model="timeData.selectTime" disabled disabledColor="#fff" placeholder="请选择日期" | |
| 9 | - border="none" suffixIcon="arrow-down"> | |
| 10 | - <template slot="prefix"> | |
| 11 | - <image class="icon" src="../../../static/can-der.png"></image> | |
| 12 | - </template> | |
| 13 | - </u-input> | |
| 14 | - </u-form-item> | |
| 15 | - <u-form-item @click="openTimeGap"> | |
| 16 | - <u-input v-model="timeData.getTimeGap" disabled disabledColor="#fff" placeholder="请选择时间区间" | |
| 17 | - border="none" suffixIcon="arrow-down"> | |
| 18 | - <template slot="prefix"> | |
| 19 | - <image class="icon" src="../../../static/time.png"></image> | |
| 20 | - </template> | |
| 21 | - </u-input> | |
| 22 | - </u-form-item> | |
| 23 | - <u-form-item @click="openAvg"> | |
| 24 | - <u-input shape="circle" v-model="aggText" placeholder="请选择数据聚合功能" disabled disabledColor="#377DFF0D" | |
| 25 | - suffixIcon="arrow-down" /> | |
| 26 | - </u-form-item> | |
| 27 | - <u-form-item @click="openTimeGap" v-if="limitFlag"> | |
| 28 | - <view class="u-flex"> | |
| 29 | - <text>最大条数</text> | |
| 30 | - <u-number-box style="margin-left:30rpx" class="ml-10" v-model="timeData.limit" :min="7" | |
| 31 | - :max="50000"></u-number-box> | |
| 32 | - </view> | |
| 33 | - </u-form-item> | |
| 34 | - <u-form-item @click="openType"> | |
| 35 | - <u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled | |
| 36 | - disabledColor="#377DFF0D" suffixIcon="arrow-down" /> | |
| 37 | - </u-form-item> | |
| 38 | - </u-form> | |
| 39 | - | |
| 40 | - <view class="charts-box" v-show="historyData.length"> | |
| 41 | - <qiun-data-charts type="area" canvas2d canvasId="daskujdhasljkdcnzjkdfhuoqwlqwjhkdsamjczxnmdasd123321" | |
| 42 | - :chartData="chartData" :ontouch="true" | |
| 43 | - :opts="{ xAxis: { disabled: true, itemCount: 6, scrollShow: true }, legend: { show: false }, enableScroll: true }" /> | |
| 44 | - </view> | |
| 45 | - <mescroll-empty v-if="!historyData.length" /> | |
| 46 | - </view> | |
| 47 | - <view class="historyData-bottom" v-show="historyData.length"> | |
| 48 | - <view class="table"> | |
| 49 | - <view class="tr bg-w" v-if="historyData.length"> | |
| 50 | - <view class="th">变量值</view> | |
| 51 | - <view class="th">更新时间</view> | |
| 52 | - </view> | |
| 53 | - <view class="tr bg-g" :class="{ odd: index % 2 === 0 }" v-for="(item, index) in historyData" | |
| 54 | - :key="index"> | |
| 55 | - <view class="td">{{ item.value }}</view> | |
| 56 | - <view class="td">{{ item.ts }}</view> | |
| 57 | - </view> | |
| 58 | - </view> | |
| 59 | - </view> | |
| 60 | - <u-calendar :show="showCalendar" :defaultDate="defaultDate" closeOnClickOverlay mode="range" startText="开始时间" | |
| 61 | - endText="结束时间" confirmDisabledText="请选择日期" :minDate="minDate" :maxDate="maxDate" @confirm="calendarConfirm" | |
| 62 | - @close="calendarClose"></u-calendar> | |
| 63 | - <u-picker :show="showTimeGap" :columns="columns" keyName="label" closeOnClickOverlay @confirm="confirmTimeGap" | |
| 64 | - @cancel="cancelTimeGap" @close="cancelTimeGap" :defaultIndex="[3]"></u-picker> | |
| 65 | - <u-picker :show="showSelectType" :columns="keys" closeOnClickOverlay @confirm="confirmTypeGap" | |
| 66 | - @cancel="cancelTypeGap" @close="cancelTypeGap"></u-picker> | |
| 67 | - <u-picker :show="showSelectAvg" :columns="avgColumns" keyName="label" closeOnClickOverlay | |
| 68 | - @confirm="confirmAvgGap" @cancel="showSelectAvg=false" @close="showSelectAvg=false"></u-picker> | |
| 69 | - </view> | |
| 70 | -</template> | |
| 71 | - | |
| 72 | -<script> | |
| 73 | - import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 74 | - import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'; | |
| 75 | - import { | |
| 76 | - getHistoryData | |
| 77 | - } from '../api/index.js'; | |
| 78 | - import { | |
| 79 | - formatToDate | |
| 80 | - } from '@/plugins/utils.js'; | |
| 81 | - const d = new Date(); | |
| 82 | - const year = d.getFullYear(); | |
| 83 | - let month = d.getMonth() + 1; | |
| 84 | - month = month < 10 ? `0${month}` : month; | |
| 85 | - const date = d.getDate(); | |
| 86 | - export default { | |
| 87 | - components: { | |
| 88 | - fTabbar, | |
| 89 | - qiunDataCharts | |
| 90 | - }, | |
| 91 | - props: { | |
| 92 | - keys: { | |
| 93 | - type: Array, | |
| 94 | - default: () => [] | |
| 95 | - }, | |
| 96 | - yesterday: { | |
| 97 | - type: String, | |
| 98 | - default: '' | |
| 99 | - }, | |
| 100 | - today: { | |
| 101 | - type: String, | |
| 102 | - default: '' | |
| 103 | - }, | |
| 104 | - timeDiff: { | |
| 105 | - type: String, | |
| 106 | - default: '' | |
| 107 | - }, | |
| 108 | - historyData: { | |
| 109 | - type: Array, | |
| 110 | - default: () => [] | |
| 111 | - }, | |
| 112 | - entityId: { | |
| 113 | - type: String, | |
| 114 | - required: true | |
| 115 | - }, | |
| 116 | - start: { | |
| 117 | - type: String, | |
| 118 | - required: true | |
| 119 | - }, | |
| 120 | - end: { | |
| 121 | - type: String, | |
| 122 | - required: true | |
| 123 | - } | |
| 124 | - }, | |
| 125 | - data() { | |
| 126 | - return { | |
| 127 | - limitFlag: true, | |
| 128 | - avgColumns: [ | |
| 129 | - [{ | |
| 130 | - label: '最小值', | |
| 131 | - value: 'MIN' | |
| 132 | - }, { | |
| 133 | - label: '最大值', | |
| 134 | - value: 'MAX' | |
| 135 | - }, | |
| 136 | - { | |
| 137 | - label: '平均值', | |
| 138 | - value: 'AVG' | |
| 139 | - }, | |
| 140 | - { | |
| 141 | - label: '求和', | |
| 142 | - value: 'SUM' | |
| 143 | - }, | |
| 144 | - { | |
| 145 | - label: '计数', | |
| 146 | - value: 'COUNT' | |
| 147 | - }, | |
| 148 | - { | |
| 149 | - label: '空', | |
| 150 | - value: 'NONE' | |
| 151 | - }, | |
| 152 | - ] | |
| 153 | - ], | |
| 154 | - startTs: this.start, | |
| 155 | - endTs: this.end, | |
| 156 | - showCalendar: false, | |
| 157 | - showTimeGap: false, | |
| 158 | - showSelectType: false, | |
| 159 | - showSelectAvg: false, | |
| 160 | - minDate: `${year}-${month - 1}-${date}`, | |
| 161 | - maxDate: `${year}-${month}-${date + 1}`, | |
| 162 | - defaultDate: [this.yesterday, this.today], | |
| 163 | - chartData: { | |
| 164 | - categories: this.historyData.length && this.historyData.map(item => item.ts), | |
| 165 | - series: [{ | |
| 166 | - name: this.keys[0][0], | |
| 167 | - data: this.historyData.length && this.historyData.map(item => Number(item.value)) | |
| 168 | - }] | |
| 169 | - }, | |
| 170 | - columns: [ | |
| 171 | - [{ | |
| 172 | - label: '5分钟', | |
| 173 | - value: 300000 | |
| 174 | - }, | |
| 175 | - { | |
| 176 | - label: '10分钟', | |
| 177 | - value: 600000 | |
| 178 | - }, | |
| 179 | - { | |
| 180 | - label: '15分钟', | |
| 181 | - value: 900000 | |
| 182 | - }, | |
| 183 | - { | |
| 184 | - label: '30分钟', | |
| 185 | - value: 1800000 | |
| 186 | - }, | |
| 187 | - { | |
| 188 | - label: '1小时', | |
| 189 | - value: 3600000 | |
| 190 | - }, | |
| 191 | - { | |
| 192 | - label: '2小时', | |
| 193 | - value: 7200000 | |
| 194 | - } | |
| 195 | - ] | |
| 196 | - ], | |
| 197 | - timeData: { | |
| 198 | - selectTime: this.yesterday + ' 至 ' + this.today, | |
| 199 | - getTimeGap: this.timeDiff, | |
| 200 | - getType: this.keys[0][0], | |
| 201 | - limit: 7, | |
| 202 | - agg: 'NONE' | |
| 203 | - }, | |
| 204 | - aggText: '空' | |
| 205 | - }; | |
| 206 | - }, | |
| 207 | - watch: { | |
| 208 | - historyData(newValue) { | |
| 209 | - if (!newValue.length) { | |
| 210 | - this.chartData.categories = []; | |
| 211 | - this.chartData.series = []; | |
| 212 | - } else { | |
| 213 | - this.chartData.categories = newValue.map(item => item.ts); | |
| 214 | - this.chartData.series = [{ | |
| 215 | - name: this.keys[0][0], | |
| 216 | - data: newValue.map(item => Number(item.value)) | |
| 217 | - }]; | |
| 218 | - } | |
| 219 | - } | |
| 220 | - }, | |
| 221 | - methods: { | |
| 222 | - // 动态生成Columns | |
| 223 | - generateColumns(value) { | |
| 224 | - if (value < 604800000) { | |
| 225 | - // 小于7天 | |
| 226 | - return [ | |
| 227 | - [{ | |
| 228 | - label: '5分钟', | |
| 229 | - value: 300000 | |
| 230 | - }, | |
| 231 | - { | |
| 232 | - label: '10分钟', | |
| 233 | - value: 600000 | |
| 234 | - }, | |
| 235 | - { | |
| 236 | - label: '15分钟', | |
| 237 | - value: 900000 | |
| 238 | - }, | |
| 239 | - { | |
| 240 | - label: '30分钟', | |
| 241 | - value: 1800000 | |
| 242 | - }, | |
| 243 | - { | |
| 244 | - label: '1小时', | |
| 245 | - value: 3600000 | |
| 246 | - }, | |
| 247 | - { | |
| 248 | - label: '2小时', | |
| 249 | - value: 7200000 | |
| 250 | - } | |
| 251 | - ] | |
| 252 | - ]; | |
| 253 | - } else if (value < 2592000000) { | |
| 254 | - // 小于30天 | |
| 255 | - return [ | |
| 256 | - [{ | |
| 257 | - label: '30分钟', | |
| 258 | - value: 1800000 | |
| 259 | - }, | |
| 260 | - { | |
| 261 | - label: '1小时', | |
| 262 | - value: 3600000 | |
| 263 | - }, | |
| 264 | - { | |
| 265 | - label: '2小时', | |
| 266 | - value: 7200000 | |
| 267 | - }, | |
| 268 | - { | |
| 269 | - label: '5小时', | |
| 270 | - value: 18000000 | |
| 271 | - }, | |
| 272 | - { | |
| 273 | - label: '10小时', | |
| 274 | - value: 36000000 | |
| 275 | - }, | |
| 276 | - { | |
| 277 | - label: '12小时', | |
| 278 | - value: 43200000 | |
| 279 | - }, | |
| 280 | - { | |
| 281 | - label: '1天', | |
| 282 | - value: 86400000 | |
| 283 | - } | |
| 284 | - ] | |
| 285 | - ]; | |
| 286 | - } else if (value >= 2592000000) { | |
| 287 | - // 大于30天 | |
| 288 | - return [ | |
| 289 | - [{ | |
| 290 | - label: '2小时', | |
| 291 | - value: 7200000 | |
| 292 | - }, | |
| 293 | - { | |
| 294 | - label: '5小时', | |
| 295 | - value: 18000000 | |
| 296 | - }, | |
| 297 | - { | |
| 298 | - label: '10小时', | |
| 299 | - value: 36000000 | |
| 300 | - }, | |
| 301 | - { | |
| 302 | - label: '12小时', | |
| 303 | - value: 43200000 | |
| 304 | - }, | |
| 305 | - { | |
| 306 | - label: '1天', | |
| 307 | - value: 86400000 | |
| 308 | - } | |
| 309 | - ] | |
| 310 | - ]; | |
| 311 | - } | |
| 312 | - }, | |
| 313 | - openCalendar() { | |
| 314 | - this.showCalendar = true; | |
| 315 | - }, | |
| 316 | - openTimeGap() { | |
| 317 | - this.showTimeGap = true; | |
| 318 | - }, | |
| 319 | - openType() { | |
| 320 | - this.showSelectType = true; | |
| 321 | - }, | |
| 322 | - openAvg() { | |
| 323 | - this.showSelectAvg = true | |
| 324 | - }, | |
| 325 | - calendarConfirm(date) { | |
| 326 | - this.showCalendar = false; | |
| 327 | - this.timeData.selectTime = `${date[0]} 至 ${date[date.length - 1]}`; | |
| 328 | - // 选择的日期时间差(时间戳) | |
| 329 | - const timeDiff = formatToDate(date[date.length - 1], 'x') - formatToDate(date[0], 'x'); | |
| 330 | - const genColumns = this.generateColumns(timeDiff); | |
| 331 | - this.columns = genColumns; | |
| 332 | - this.timeData.getTimeGap = ''; | |
| 333 | - this.timeData.getType = ''; | |
| 334 | - this.startTs = formatToDate(date[0], 'x'); | |
| 335 | - // 最后时间的最后一秒 | |
| 336 | - this.endTs = formatToDate(`${date[date.length - 1]} 23:59:59`, 'x'); | |
| 337 | - }, | |
| 338 | - calendarClose() { | |
| 339 | - this.showCalendar = false; | |
| 340 | - }, | |
| 341 | - confirmTimeGap(time) { | |
| 342 | - this.showTimeGap = false; | |
| 343 | - this.timeData.getTimeGap = time.value[0].label; | |
| 344 | - this.timeData.getType = ''; | |
| 345 | - }, | |
| 346 | - | |
| 347 | - cancelTimeGap() { | |
| 348 | - this.showTimeGap = false; | |
| 349 | - }, | |
| 350 | - confirmAvgGap(e) { | |
| 351 | - this.timeData.agg = e.value[0].value | |
| 352 | - this.aggText = e.value[0].label | |
| 353 | - if (e.value[0].value === 'NONE') { | |
| 354 | - this.limitFlag = true | |
| 355 | - this.timeData.limit = 7 | |
| 356 | - } else { | |
| 357 | - this.timeData.limit = null | |
| 358 | - this.limitFlag = false | |
| 359 | - } | |
| 360 | - this.showSelectAvg = false | |
| 361 | - }, | |
| 362 | - async confirmTypeGap(time) { | |
| 363 | - this.showSelectType = false; | |
| 364 | - this.timeData.getType = time.value[0]; | |
| 365 | - const interval = this.columns[0].find(item => item.label === this.timeData.getTimeGap); | |
| 366 | - const data = await getHistoryData({ | |
| 367 | - startTs: this.startTs, | |
| 368 | - endTs: this.endTs, | |
| 369 | - keys: this.timeData.getType, | |
| 370 | - interval: this.limitFlag ? null : interval.value, | |
| 371 | - entityId: this.entityId, | |
| 372 | - limit: this.timeData.limit, | |
| 373 | - agg: this.timeData.agg | |
| 374 | - }); | |
| 375 | - this.$emit('update', data[this.timeData.getType]); | |
| 376 | - }, | |
| 377 | - cancelTypeGap() { | |
| 378 | - this.showSelectType = false; | |
| 379 | - } | |
| 380 | - } | |
| 381 | - }; | |
| 382 | -</script> | |
| 383 | - | |
| 384 | -<style lang="scss" scoped> | |
| 385 | - .charts-box { | |
| 386 | - width: 100%; | |
| 387 | - height: 550rpx; | |
| 388 | - } | |
| 389 | - | |
| 390 | - .historyData { | |
| 391 | - margin: 30rpx; | |
| 392 | - | |
| 393 | - .historyData-top { | |
| 394 | - padding: 30rpx; | |
| 395 | - background-color: #fff; | |
| 396 | - // height: 870rpx; | |
| 397 | - border-radius: 20rpx; | |
| 398 | - | |
| 399 | - .icon { | |
| 400 | - width: 28rpx; | |
| 401 | - height: 28rpx; | |
| 402 | - margin-right: 15rpx; | |
| 403 | - } | |
| 404 | - } | |
| 405 | - | |
| 406 | - .historyData-bottom { | |
| 407 | - margin-top: 30rpx; | |
| 408 | - background-color: #fff; | |
| 409 | - border-radius: 20rpx; | |
| 410 | - | |
| 411 | - .table { | |
| 412 | - border: 0px solid darkgray; | |
| 413 | - | |
| 414 | - .tr { | |
| 415 | - display: flex; | |
| 416 | - width: 100%; | |
| 417 | - justify-content: center; | |
| 418 | - height: 3rem; | |
| 419 | - align-items: center; | |
| 420 | - | |
| 421 | - .th { | |
| 422 | - display: flex; | |
| 423 | - justify-content: center; | |
| 424 | - align-items: center; | |
| 425 | - width: 50%; | |
| 426 | - color: #333; | |
| 427 | - font-weight: 500; | |
| 428 | - } | |
| 429 | - | |
| 430 | - .td { | |
| 431 | - color: #999; | |
| 432 | - width: 50%; | |
| 433 | - display: flex; | |
| 434 | - justify-content: center; | |
| 435 | - text-align: center; | |
| 436 | - } | |
| 437 | - } | |
| 438 | - } | |
| 439 | - } | |
| 440 | - } | |
| 441 | - | |
| 442 | - .odd { | |
| 443 | - background-color: #f9fcff; | |
| 444 | - } | |
| 1 | +<template> | |
| 2 | + <view class="historyData"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view class="historyData-top"> | |
| 6 | + <u-form :label-style="{ 'font-size': '0rpx' }"> | |
| 7 | + <u-form-item @click="openCalendar"> | |
| 8 | + <u-input v-model="timeData.selectTime" disabled disabledColor="#fff" placeholder="请选择日期" | |
| 9 | + border="none" suffixIcon="arrow-down"> | |
| 10 | + <template slot="prefix"> | |
| 11 | + <image class="icon" src="../../../static/can-der.png"></image> | |
| 12 | + </template> | |
| 13 | + </u-input> | |
| 14 | + </u-form-item> | |
| 15 | + <u-form-item @click="openTimeGap"> | |
| 16 | + <u-input v-model="timeData.getTimeGap" disabled disabledColor="#fff" placeholder="请选择时间区间" | |
| 17 | + border="none" suffixIcon="arrow-down"> | |
| 18 | + <template slot="prefix"> | |
| 19 | + <image class="icon" src="../../../static/time.png"></image> | |
| 20 | + </template> | |
| 21 | + </u-input> | |
| 22 | + </u-form-item> | |
| 23 | + <u-form-item @click="openAvg"> | |
| 24 | + <u-input shape="circle" v-model="aggText" placeholder="请选择数据聚合功能" disabled disabledColor="#377DFF0D" | |
| 25 | + suffixIcon="arrow-down" /> | |
| 26 | + </u-form-item> | |
| 27 | + <u-form-item @click="openTimeGap" v-if="limitFlag"> | |
| 28 | + <view class="u-flex"> | |
| 29 | + <text>最大条数</text> | |
| 30 | + <u-number-box style="margin-left:30rpx" class="ml-10" v-model="timeData.limit" :min="7" | |
| 31 | + :max="50000"></u-number-box> | |
| 32 | + </view> | |
| 33 | + </u-form-item> | |
| 34 | + <u-form-item @click="openType"> | |
| 35 | + <u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled | |
| 36 | + disabledColor="#377DFF0D" suffixIcon="arrow-down" /> | |
| 37 | + </u-form-item> | |
| 38 | + </u-form> | |
| 39 | + | |
| 40 | + <view class="charts-box" v-show="historyData.length"> | |
| 41 | + <qiun-data-charts type="area" canvas2d canvasId="daskujdhasljkdcnzjkdfhuoqwlqwjhkdsamjczxnmdasd123321" | |
| 42 | + :chartData="chartData" :ontouch="true" | |
| 43 | + :opts="{ xAxis: { disabled: true, itemCount: 6, scrollShow: true }, legend: { show: false }, enableScroll: true }" /> | |
| 44 | + </view> | |
| 45 | + <mescroll-empty v-if="!historyData.length" /> | |
| 46 | + </view> | |
| 47 | + <view class="historyData-bottom" v-show="historyData.length"> | |
| 48 | + <view class="table"> | |
| 49 | + <view class="tr bg-w" v-if="historyData.length"> | |
| 50 | + <view class="th">变量值</view> | |
| 51 | + <view class="th">更新时间</view> | |
| 52 | + </view> | |
| 53 | + <view class="tr bg-g" :class="{ odd: index % 2 === 0 }" v-for="(item, index) in historyData" | |
| 54 | + :key="index"> | |
| 55 | + <view class="td">{{ item.value }}</view> | |
| 56 | + <view class="td">{{ item.ts }}</view> | |
| 57 | + </view> | |
| 58 | + </view> | |
| 59 | + </view> | |
| 60 | + <u-calendar :show="showCalendar" :defaultDate="defaultDate" closeOnClickOverlay mode="range" startText="开始时间" | |
| 61 | + endText="结束时间" confirmDisabledText="请选择日期" :minDate="minDate" :maxDate="maxDate" @confirm="calendarConfirm" | |
| 62 | + @close="calendarClose"></u-calendar> | |
| 63 | + <u-picker :show="showTimeGap" :columns="columns" keyName="label" closeOnClickOverlay @confirm="confirmTimeGap" | |
| 64 | + @cancel="cancelTimeGap" @close="cancelTimeGap" :defaultIndex="[3]"></u-picker> | |
| 65 | + <u-picker :show="showSelectType" :columns="keys" closeOnClickOverlay @confirm="confirmTypeGap" | |
| 66 | + @cancel="cancelTypeGap" @close="cancelTypeGap"></u-picker> | |
| 67 | + <u-picker :show="showSelectAvg" :columns="avgColumns" keyName="label" closeOnClickOverlay | |
| 68 | + @confirm="confirmAvgGap" @cancel="showSelectAvg=false" @close="showSelectAvg=false"></u-picker> | |
| 69 | + </view> | |
| 70 | +</template> | |
| 71 | + | |
| 72 | +<script> | |
| 73 | + import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 74 | + import qiunDataCharts from './uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'; | |
| 75 | + import { | |
| 76 | + getHistoryData | |
| 77 | + } from '../api/index.js'; | |
| 78 | + import { | |
| 79 | + formatToDate | |
| 80 | + } from '@/plugins/utils.js'; | |
| 81 | + const d = new Date(); | |
| 82 | + const year = d.getFullYear(); | |
| 83 | + let month = d.getMonth() + 1; | |
| 84 | + month = month < 10 ? `0${month}` : month; | |
| 85 | + const date = d.getDate(); | |
| 86 | + export default { | |
| 87 | + components: { | |
| 88 | + fTabbar, | |
| 89 | + qiunDataCharts | |
| 90 | + }, | |
| 91 | + props: { | |
| 92 | + keys: { | |
| 93 | + type: Array, | |
| 94 | + default: () => [] | |
| 95 | + }, | |
| 96 | + yesterday: { | |
| 97 | + type: String, | |
| 98 | + default: '' | |
| 99 | + }, | |
| 100 | + today: { | |
| 101 | + type: String, | |
| 102 | + default: '' | |
| 103 | + }, | |
| 104 | + timeDiff: { | |
| 105 | + type: String, | |
| 106 | + default: '' | |
| 107 | + }, | |
| 108 | + historyData: { | |
| 109 | + type: Array, | |
| 110 | + default: () => [] | |
| 111 | + }, | |
| 112 | + entityId: { | |
| 113 | + type: String, | |
| 114 | + required: true | |
| 115 | + }, | |
| 116 | + start: { | |
| 117 | + type: String, | |
| 118 | + required: true | |
| 119 | + }, | |
| 120 | + end: { | |
| 121 | + type: String, | |
| 122 | + required: true | |
| 123 | + } | |
| 124 | + }, | |
| 125 | + data() { | |
| 126 | + return { | |
| 127 | + limitFlag: true, | |
| 128 | + avgColumns: [ | |
| 129 | + [{ | |
| 130 | + label: '最小值', | |
| 131 | + value: 'MIN' | |
| 132 | + }, { | |
| 133 | + label: '最大值', | |
| 134 | + value: 'MAX' | |
| 135 | + }, | |
| 136 | + { | |
| 137 | + label: '平均值', | |
| 138 | + value: 'AVG' | |
| 139 | + }, | |
| 140 | + { | |
| 141 | + label: '求和', | |
| 142 | + value: 'SUM' | |
| 143 | + }, | |
| 144 | + { | |
| 145 | + label: '计数', | |
| 146 | + value: 'COUNT' | |
| 147 | + }, | |
| 148 | + { | |
| 149 | + label: '空', | |
| 150 | + value: 'NONE' | |
| 151 | + }, | |
| 152 | + ] | |
| 153 | + ], | |
| 154 | + startTs: this.start, | |
| 155 | + endTs: this.end, | |
| 156 | + showCalendar: false, | |
| 157 | + showTimeGap: false, | |
| 158 | + showSelectType: false, | |
| 159 | + showSelectAvg: false, | |
| 160 | + minDate: `${year}-${month - 1}-${date}`, | |
| 161 | + maxDate: `${year}-${month}-${date + 1}`, | |
| 162 | + defaultDate: [this.yesterday, this.today], | |
| 163 | + chartData: { | |
| 164 | + categories: this.historyData.length && this.historyData.map(item => item.ts), | |
| 165 | + series: [{ | |
| 166 | + name: this.keys[0][0], | |
| 167 | + data: this.historyData.length && this.historyData.map(item => Number(item.value)) | |
| 168 | + }] | |
| 169 | + }, | |
| 170 | + columns: [ | |
| 171 | + [{ | |
| 172 | + label: '5分钟', | |
| 173 | + value: 300000 | |
| 174 | + }, | |
| 175 | + { | |
| 176 | + label: '10分钟', | |
| 177 | + value: 600000 | |
| 178 | + }, | |
| 179 | + { | |
| 180 | + label: '15分钟', | |
| 181 | + value: 900000 | |
| 182 | + }, | |
| 183 | + { | |
| 184 | + label: '30分钟', | |
| 185 | + value: 1800000 | |
| 186 | + }, | |
| 187 | + { | |
| 188 | + label: '1小时', | |
| 189 | + value: 3600000 | |
| 190 | + }, | |
| 191 | + { | |
| 192 | + label: '2小时', | |
| 193 | + value: 7200000 | |
| 194 | + } | |
| 195 | + ] | |
| 196 | + ], | |
| 197 | + timeData: { | |
| 198 | + selectTime: this.yesterday + ' 至 ' + this.today, | |
| 199 | + getTimeGap: this.timeDiff, | |
| 200 | + getType: this.keys[0][0], | |
| 201 | + limit: 7, | |
| 202 | + agg: 'NONE' | |
| 203 | + }, | |
| 204 | + aggText: '空' | |
| 205 | + }; | |
| 206 | + }, | |
| 207 | + watch: { | |
| 208 | + historyData(newValue) { | |
| 209 | + if (!newValue.length) { | |
| 210 | + this.chartData.categories = []; | |
| 211 | + this.chartData.series = []; | |
| 212 | + } else { | |
| 213 | + this.chartData.categories = newValue.map(item => item.ts); | |
| 214 | + this.chartData.series = [{ | |
| 215 | + name: this.keys[0][0], | |
| 216 | + data: newValue.map(item => Number(item.value)) | |
| 217 | + }]; | |
| 218 | + } | |
| 219 | + } | |
| 220 | + }, | |
| 221 | + methods: { | |
| 222 | + // 动态生成Columns | |
| 223 | + generateColumns(value) { | |
| 224 | + if (value < 604800000) { | |
| 225 | + // 小于7天 | |
| 226 | + return [ | |
| 227 | + [{ | |
| 228 | + label: '5分钟', | |
| 229 | + value: 300000 | |
| 230 | + }, | |
| 231 | + { | |
| 232 | + label: '10分钟', | |
| 233 | + value: 600000 | |
| 234 | + }, | |
| 235 | + { | |
| 236 | + label: '15分钟', | |
| 237 | + value: 900000 | |
| 238 | + }, | |
| 239 | + { | |
| 240 | + label: '30分钟', | |
| 241 | + value: 1800000 | |
| 242 | + }, | |
| 243 | + { | |
| 244 | + label: '1小时', | |
| 245 | + value: 3600000 | |
| 246 | + }, | |
| 247 | + { | |
| 248 | + label: '2小时', | |
| 249 | + value: 7200000 | |
| 250 | + } | |
| 251 | + ] | |
| 252 | + ]; | |
| 253 | + } else if (value < 2592000000) { | |
| 254 | + // 小于30天 | |
| 255 | + return [ | |
| 256 | + [{ | |
| 257 | + label: '30分钟', | |
| 258 | + value: 1800000 | |
| 259 | + }, | |
| 260 | + { | |
| 261 | + label: '1小时', | |
| 262 | + value: 3600000 | |
| 263 | + }, | |
| 264 | + { | |
| 265 | + label: '2小时', | |
| 266 | + value: 7200000 | |
| 267 | + }, | |
| 268 | + { | |
| 269 | + label: '5小时', | |
| 270 | + value: 18000000 | |
| 271 | + }, | |
| 272 | + { | |
| 273 | + label: '10小时', | |
| 274 | + value: 36000000 | |
| 275 | + }, | |
| 276 | + { | |
| 277 | + label: '12小时', | |
| 278 | + value: 43200000 | |
| 279 | + }, | |
| 280 | + { | |
| 281 | + label: '1天', | |
| 282 | + value: 86400000 | |
| 283 | + } | |
| 284 | + ] | |
| 285 | + ]; | |
| 286 | + } else if (value >= 2592000000) { | |
| 287 | + // 大于30天 | |
| 288 | + return [ | |
| 289 | + [{ | |
| 290 | + label: '2小时', | |
| 291 | + value: 7200000 | |
| 292 | + }, | |
| 293 | + { | |
| 294 | + label: '5小时', | |
| 295 | + value: 18000000 | |
| 296 | + }, | |
| 297 | + { | |
| 298 | + label: '10小时', | |
| 299 | + value: 36000000 | |
| 300 | + }, | |
| 301 | + { | |
| 302 | + label: '12小时', | |
| 303 | + value: 43200000 | |
| 304 | + }, | |
| 305 | + { | |
| 306 | + label: '1天', | |
| 307 | + value: 86400000 | |
| 308 | + } | |
| 309 | + ] | |
| 310 | + ]; | |
| 311 | + } | |
| 312 | + }, | |
| 313 | + openCalendar() { | |
| 314 | + this.showCalendar = true; | |
| 315 | + }, | |
| 316 | + openTimeGap() { | |
| 317 | + this.showTimeGap = true; | |
| 318 | + }, | |
| 319 | + openType() { | |
| 320 | + this.showSelectType = true; | |
| 321 | + }, | |
| 322 | + openAvg() { | |
| 323 | + this.showSelectAvg = true | |
| 324 | + }, | |
| 325 | + calendarConfirm(date) { | |
| 326 | + this.showCalendar = false; | |
| 327 | + this.timeData.selectTime = `${date[0]} 至 ${date[date.length - 1]}`; | |
| 328 | + // 选择的日期时间差(时间戳) | |
| 329 | + const timeDiff = formatToDate(date[date.length - 1], 'x') - formatToDate(date[0], 'x'); | |
| 330 | + const genColumns = this.generateColumns(timeDiff); | |
| 331 | + this.columns = genColumns; | |
| 332 | + this.timeData.getTimeGap = ''; | |
| 333 | + this.timeData.getType = ''; | |
| 334 | + this.startTs = formatToDate(date[0], 'x'); | |
| 335 | + // 最后时间的最后一秒 | |
| 336 | + this.endTs = formatToDate(`${date[date.length - 1]} 23:59:59`, 'x'); | |
| 337 | + }, | |
| 338 | + calendarClose() { | |
| 339 | + this.showCalendar = false; | |
| 340 | + }, | |
| 341 | + confirmTimeGap(time) { | |
| 342 | + this.showTimeGap = false; | |
| 343 | + this.timeData.getTimeGap = time.value[0].label; | |
| 344 | + this.timeData.getType = ''; | |
| 345 | + }, | |
| 346 | + | |
| 347 | + cancelTimeGap() { | |
| 348 | + this.showTimeGap = false; | |
| 349 | + }, | |
| 350 | + confirmAvgGap(e) { | |
| 351 | + this.timeData.agg = e.value[0].value | |
| 352 | + this.aggText = e.value[0].label | |
| 353 | + if (e.value[0].value === 'NONE') { | |
| 354 | + this.limitFlag = true | |
| 355 | + this.timeData.limit = 7 | |
| 356 | + } else { | |
| 357 | + this.timeData.limit = null | |
| 358 | + this.limitFlag = false | |
| 359 | + } | |
| 360 | + this.showSelectAvg = false | |
| 361 | + }, | |
| 362 | + async confirmTypeGap(time) { | |
| 363 | + this.showSelectType = false; | |
| 364 | + this.timeData.getType = time.value[0]; | |
| 365 | + const interval = this.columns[0].find(item => item.label === this.timeData.getTimeGap); | |
| 366 | + const data = await getHistoryData({ | |
| 367 | + startTs: this.startTs, | |
| 368 | + endTs: this.endTs, | |
| 369 | + keys: this.timeData.getType, | |
| 370 | + interval: this.limitFlag ? null : interval.value, | |
| 371 | + entityId: this.entityId, | |
| 372 | + limit: this.timeData.limit, | |
| 373 | + agg: this.timeData.agg | |
| 374 | + }); | |
| 375 | + this.$emit('update', data[this.timeData.getType]); | |
| 376 | + }, | |
| 377 | + cancelTypeGap() { | |
| 378 | + this.showSelectType = false; | |
| 379 | + } | |
| 380 | + } | |
| 381 | + }; | |
| 382 | +</script> | |
| 383 | + | |
| 384 | +<style lang="scss" scoped> | |
| 385 | + .charts-box { | |
| 386 | + width: 100%; | |
| 387 | + height: 550rpx; | |
| 388 | + } | |
| 389 | + | |
| 390 | + .historyData { | |
| 391 | + margin: 30rpx; | |
| 392 | + | |
| 393 | + .historyData-top { | |
| 394 | + padding: 30rpx; | |
| 395 | + background-color: #fff; | |
| 396 | + // height: 870rpx; | |
| 397 | + border-radius: 20rpx; | |
| 398 | + | |
| 399 | + .icon { | |
| 400 | + width: 28rpx; | |
| 401 | + height: 28rpx; | |
| 402 | + margin-right: 15rpx; | |
| 403 | + } | |
| 404 | + } | |
| 405 | + | |
| 406 | + .historyData-bottom { | |
| 407 | + margin-top: 30rpx; | |
| 408 | + background-color: #fff; | |
| 409 | + border-radius: 20rpx; | |
| 410 | + | |
| 411 | + .table { | |
| 412 | + border: 0px solid darkgray; | |
| 413 | + | |
| 414 | + .tr { | |
| 415 | + display: flex; | |
| 416 | + width: 100%; | |
| 417 | + justify-content: center; | |
| 418 | + height: 3rem; | |
| 419 | + align-items: center; | |
| 420 | + | |
| 421 | + .th { | |
| 422 | + display: flex; | |
| 423 | + justify-content: center; | |
| 424 | + align-items: center; | |
| 425 | + width: 50%; | |
| 426 | + color: #333; | |
| 427 | + font-weight: 500; | |
| 428 | + } | |
| 429 | + | |
| 430 | + .td { | |
| 431 | + color: #999; | |
| 432 | + width: 50%; | |
| 433 | + display: flex; | |
| 434 | + justify-content: center; | |
| 435 | + text-align: center; | |
| 436 | + } | |
| 437 | + } | |
| 438 | + } | |
| 439 | + } | |
| 440 | + } | |
| 441 | + | |
| 442 | + .odd { | |
| 443 | + background-color: #f9fcff; | |
| 444 | + } | |
| 445 | 445 | </style> | ... | ... |
| 1 | +<template> | |
| 2 | + <view class="mp-u-modal"> | |
| 3 | + <u-modal :mask-close-able="true" :show="showModal" closeOnClickOverlay :showConfirmButton="false" | |
| 4 | + @close="$emit('hideModal')" @touchmove.stop.prevent="disabledScroll" z-index="99999"> | |
| 5 | + <view class="w-100 modal-content"> | |
| 6 | + <view class="header-title">命令下发</view> | |
| 7 | + <view class="u-flex"> | |
| 8 | + <text class="type-text">下发类型:</text> | |
| 9 | + <u-radio-group v-model="commandType" placement="row"> | |
| 10 | + <u-radio activeColor="#3388FF" label="单向" name="OneWay"></u-radio> | |
| 11 | + <view style="margin: 0 20rpx;"></view> | |
| 12 | + <u-radio activeColor="#3388FF" label="双向" name="TwoWay"></u-radio> | |
| 13 | + </u-radio-group> | |
| 14 | + </view> | |
| 15 | + <view class="content-body"> | |
| 16 | + <div class="u-flex u-row-between"> | |
| 17 | + <u--textarea :placeholder="`请输入下发内容${isShowTCP?'(字符串格式)':'(json格式)'}`" | |
| 18 | + v-model="inputCommandVal" /> | |
| 19 | + <u-icon v-if="!isShowTCP" @click="handleCopy(copyTextValue)" name="question-circle" | |
| 20 | + color="#2979ff" size="28" class="ml-10"> | |
| 21 | + </u-icon> | |
| 22 | + </div> | |
| 23 | + </view> | |
| 24 | + <view class="button-group"> | |
| 25 | + <view> | |
| 26 | + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="取消" | |
| 27 | + @click="cancelCommand"></u-button> | |
| 28 | + </view> | |
| 29 | + <view> | |
| 30 | + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmCommand"></u-button> | |
| 31 | + </view> | |
| 32 | + </view> | |
| 33 | + </view> | |
| 34 | + </u-modal> | |
| 35 | + </view> | |
| 36 | +</template> | |
| 37 | + | |
| 38 | +<script> | |
| 39 | + import { | |
| 40 | + useShowModal | |
| 41 | + } from '@/plugins/utils.js' | |
| 42 | + | |
| 43 | + export default { | |
| 44 | + props: { | |
| 45 | + showModal: Boolean, | |
| 46 | + isShowTCP: Boolean | |
| 47 | + }, | |
| 48 | + data() { | |
| 49 | + return { | |
| 50 | + current: 0, | |
| 51 | + commandType: 'OneWay', | |
| 52 | + inputCommandVal: '', | |
| 53 | + copyTextValue: { | |
| 54 | + "method": "methodThingskit", | |
| 55 | + "params": { | |
| 56 | + "pin": 7, | |
| 57 | + "value": 1 | |
| 58 | + } | |
| 59 | + } | |
| 60 | + } | |
| 61 | + }, | |
| 62 | + methods: { | |
| 63 | + cancelCommand() { | |
| 64 | + this.$emit('cancelCommand') | |
| 65 | + }, | |
| 66 | + confirmCommand() { | |
| 67 | + this.$emit('confirmCommand', this.commandType, this.inputCommandVal) | |
| 68 | + }, | |
| 69 | + handleCopy(value) { | |
| 70 | + useShowModal(JSON.stringify(value), '命令下发', '复制内容').then(res => { | |
| 71 | + uni.setClipboardData({ | |
| 72 | + data: JSON.stringify(value), | |
| 73 | + success: () => { | |
| 74 | + uni.showToast({ | |
| 75 | + title: '复制成功' | |
| 76 | + }) | |
| 77 | + } | |
| 78 | + }); | |
| 79 | + }) | |
| 80 | + }, | |
| 81 | + reset() { | |
| 82 | + this.commandType = 'OneWay' | |
| 83 | + this.inputCommandVal = '' | |
| 84 | + } | |
| 85 | + } | |
| 86 | + } | |
| 87 | +</script> | |
| 88 | + | |
| 89 | +<style lang="scss" scoped> | |
| 90 | + .modal-content { | |
| 91 | + width: 720rpx; | |
| 92 | + padding: 0 30rpx; | |
| 93 | + background-color: white; | |
| 94 | + | |
| 95 | + .header-title { | |
| 96 | + text-align: center; | |
| 97 | + font-weight: 700; | |
| 98 | + margin-bottom: 40rpx; | |
| 99 | + } | |
| 100 | + | |
| 101 | + .type-text { | |
| 102 | + color: #333; | |
| 103 | + font-size: 14px; | |
| 104 | + font-weight: 700; | |
| 105 | + margin-right: 30rpx; | |
| 106 | + } | |
| 107 | + | |
| 108 | + .content-body { | |
| 109 | + margin-top: 28rpx; | |
| 110 | + width: 100%; | |
| 111 | + } | |
| 112 | + | |
| 113 | + .button-group { | |
| 114 | + display: flex; | |
| 115 | + margin-top: 40rpx; | |
| 116 | + justify-content: space-between; | |
| 117 | + | |
| 118 | + view { | |
| 119 | + width: 300rpx; | |
| 120 | + } | |
| 121 | + } | |
| 122 | + } | |
| 123 | +</style> | |
| \ No newline at end of file | ... | ... |
| 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 class="item-value">{{ item.value }}</view> | |
| 7 | + </view> | |
| 8 | + <view class="item-time">{{ item.time }}</view> | |
| 9 | + </view> | |
| 10 | + <mescroll-empty v-if="!recordList.length" /> | |
| 11 | + </view> | |
| 12 | +</template> | |
| 13 | + | |
| 14 | +<script> | |
| 15 | + export default { | |
| 16 | + props: { | |
| 17 | + recordList: { | |
| 18 | + type: Array, | |
| 19 | + default: () => [] | |
| 20 | + } | |
| 21 | + } | |
| 22 | + }; | |
| 23 | +</script> | |
| 24 | + | |
| 25 | +<style lang="scss" scoped> | |
| 26 | + @import "../static/realtime-data.scss"; | |
| 27 | +</style> | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/changelog.md
renamed from
uni_modules/qiun-data-charts/changelog.md
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue
renamed from
uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
renamed from
uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
renamed from
uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
renamed from
uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
renamed from
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/license.md
renamed from
uni_modules/qiun-data-charts/license.md
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/package.json
renamed from
uni_modules/qiun-data-charts/package.json
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/readme.md
renamed from
uni_modules/qiun-data-charts/readme.md
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
renamed from
uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
device-subpackage/device-detail/components/uni_modules/qiun-data-charts/static/h5/echarts.min.js
renamed from
uni_modules/qiun-data-charts/static/h5/echarts.min.js
| 1 | +const list = [{ | |
| 2 | + name: "基础信息", | |
| 3 | + }, | |
| 4 | + { | |
| 5 | + name: "实时数据", | |
| 6 | + }, | |
| 7 | + { | |
| 8 | + name: "历史数据", | |
| 9 | + }, | |
| 10 | + { | |
| 11 | + name: "告警记录", | |
| 12 | + }, | |
| 13 | +] | |
| 14 | + | |
| 15 | +const issueStatus = [{ | |
| 16 | + checked: true, | |
| 17 | + name: '全部', | |
| 18 | + type: '' | |
| 19 | + }, | |
| 20 | + { | |
| 21 | + checked: false, | |
| 22 | + name: '队列中', | |
| 23 | + type: 'QUEUED' | |
| 24 | + }, | |
| 25 | + { | |
| 26 | + checked: false, | |
| 27 | + name: '已发送', | |
| 28 | + type: 'SENT' | |
| 29 | + }, | |
| 30 | + { | |
| 31 | + checked: false, | |
| 32 | + name: '发送成功', | |
| 33 | + type: 'DELIVERED' | |
| 34 | + }, | |
| 35 | + { | |
| 36 | + checked: false, | |
| 37 | + name: '响应成功', | |
| 38 | + type: 'SUCCESSFUL' | |
| 39 | + }, | |
| 40 | + { | |
| 41 | + checked: false, | |
| 42 | + name: '超时', | |
| 43 | + type: 'TIMEOUT' | |
| 44 | + }, | |
| 45 | + { | |
| 46 | + checked: false, | |
| 47 | + name: '已过期', | |
| 48 | + type: 'EXPIRED' | |
| 49 | + }, | |
| 50 | + { | |
| 51 | + checked: false, | |
| 52 | + name: '响应失败', | |
| 53 | + type: 'FAILED' | |
| 54 | + }, | |
| 55 | + { | |
| 56 | + checked: false, | |
| 57 | + name: '已删除', | |
| 58 | + type: 'DELETED' | |
| 59 | + } | |
| 60 | +] | |
| 61 | + | |
| 62 | +const commandTypeList = [{ | |
| 63 | + value: 'OneWay', | |
| 64 | + name: '单向', | |
| 65 | + }, | |
| 66 | + { | |
| 67 | + value: 'TwoWay', | |
| 68 | + name: '双向' | |
| 69 | + }, | |
| 70 | +] | |
| 71 | + | |
| 72 | + | |
| 73 | +export { | |
| 74 | + list, | |
| 75 | + issueStatus, | |
| 76 | + commandTypeList | |
| 77 | +} | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/device-detail.vue
renamed from
deviceSubPage/deviceDetailPage/deviceDetail.vue
| 1 | -<template> | |
| 2 | - <view class="device-detail-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <u-sticky bgColor="#fff"> | |
| 6 | - <u-tabs :list="list" :current="currentTab" @click="handleTabClick" :activeStyle="{ | |
| 7 | - fontWeight: 'bold', | |
| 8 | - color: '#333', | |
| 9 | - }" :inactiveStyle="{ | |
| 10 | - color: '#999', | |
| 11 | - }" :scrollable="isScrollable" /> | |
| 12 | - </u-sticky> | |
| 13 | - <view style="margin-top: 30rpx"> | |
| 14 | - <basicInfo v-show="currentTab == 0" :deviceDetail="deviceDetail" /> | |
| 15 | - <realTimeData v-show="currentTab === 1" :recordList="recordList" /> | |
| 16 | - <historyData v-if="currentTab === 2" :keys="keys" :yesterday="yesterday" :today="today" :timeDiff="timeDiff" | |
| 17 | - :historyData="historyData" :entityId="entityId" :start="startTs" :end="endTs" @update="handleUpdate" /> | |
| 18 | - <alarmHistory v-show="currentTab === 3" :deviceId="deviceId" /> | |
| 19 | - <commondRecord v-if="currentTab === 4" :tbDeviceId="entityId" /> | |
| 20 | - </view> | |
| 21 | - </view> | |
| 22 | -</template> | |
| 23 | - | |
| 24 | -<script> | |
| 25 | - import fTabbar from "@/components/module/f-tabbar/f-tabbar"; | |
| 26 | - import basicInfo from "./tabDetail/basicInfo.vue"; | |
| 27 | - import realTimeData from "./tabDetail/realtimeData.vue"; | |
| 28 | - import alarmHistory from "./tabDetail/alarmHistory.vue"; | |
| 29 | - import historyData from "./tabDetail/historyData.vue"; | |
| 30 | - import commondRecord from "./tabDetail/CommandRecord.vue"; | |
| 31 | - import { | |
| 32 | - getDeviceKeys, | |
| 33 | - getHistoryData | |
| 34 | - } from "./api/index.js"; | |
| 35 | - import { | |
| 36 | - formatToDate | |
| 37 | - } from "@/plugins/utils.js"; | |
| 38 | - import MescrollCompMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js"; | |
| 39 | - import moment from "moment"; | |
| 40 | - import base from "@/config/baseUrl.js"; | |
| 41 | - | |
| 42 | - export default { | |
| 43 | - mixins: [MescrollCompMixin], | |
| 44 | - components: { | |
| 45 | - fTabbar, | |
| 46 | - basicInfo, | |
| 47 | - realTimeData, | |
| 48 | - alarmHistory, | |
| 49 | - historyData, | |
| 50 | - commondRecord, | |
| 51 | - }, | |
| 52 | - data() { | |
| 53 | - return { | |
| 54 | - list: [{ | |
| 55 | - name: "基础信息", | |
| 56 | - }, | |
| 57 | - { | |
| 58 | - name: "实时数据", | |
| 59 | - }, | |
| 60 | - { | |
| 61 | - name: "历史数据", | |
| 62 | - }, | |
| 63 | - { | |
| 64 | - name: "告警记录", | |
| 65 | - }, | |
| 66 | - ], | |
| 67 | - currentTab: 0, | |
| 68 | - deviceId: "", | |
| 69 | - deviceDetail: {}, | |
| 70 | - keys: [], | |
| 71 | - yesterday: "", | |
| 72 | - today: "", | |
| 73 | - timeDiff: "", | |
| 74 | - historyData: [], | |
| 75 | - entityId: "", | |
| 76 | - startTs: "", | |
| 77 | - endTs: "", | |
| 78 | - recordList: [], | |
| 79 | - isScrollable: false, | |
| 80 | - attrList: [] | |
| 81 | - }; | |
| 82 | - }, | |
| 83 | - onUnload() { | |
| 84 | - // 页面关闭时,销毁webSocket连接,否则第二次会存在连接不到的情况 | |
| 85 | - uni.closeSocket(); | |
| 86 | - }, | |
| 87 | - async onLoad(options) { | |
| 88 | - const { | |
| 89 | - id, | |
| 90 | - alarmStatus, | |
| 91 | - lastOnlineTime, | |
| 92 | - tbDeviceId, | |
| 93 | - deviceProfileId | |
| 94 | - } = | |
| 95 | - options; | |
| 96 | - this.deviceId = id; | |
| 97 | - const res = await uni.$u.http.get(`/yt/device/${id}`); | |
| 98 | - this.deviceDetail = { | |
| 99 | - ...res, | |
| 100 | - alarmStatus, | |
| 101 | - lastOnlineTime, | |
| 102 | - }; | |
| 103 | - | |
| 104 | - // 设备类型不是网关子设备的添加一个命令记录的选项卡 | |
| 105 | - if (this.deviceDetail.deviceType !== "SENSOR") { | |
| 106 | - this.list.push({ | |
| 107 | - name: "命令记录", | |
| 108 | - }); | |
| 109 | - } | |
| 110 | - this.isScrollable = this.list.length > 4; | |
| 111 | - if (res.deviceProfileId) { | |
| 112 | - const getAttrList = await uni.$u.http.get( | |
| 113 | - `/yt/device/attributes/${res.deviceProfileId}` | |
| 114 | - ); | |
| 115 | - if (Array.isArray(getAttrList)) { | |
| 116 | - this.attrList = getAttrList.map(m => { | |
| 117 | - return m.identifier | |
| 118 | - }) | |
| 119 | - } | |
| 120 | - } | |
| 121 | - // 连接webSockte | |
| 122 | - const socketTask = uni.connectSocket({ | |
| 123 | - url: `${base.socketPrefix}://${base.baseWebSocketUrl}/api/ws/plugins/telemetry?token=` + | |
| 124 | - uni.getStorageSync("userInfo").isToken, //仅为示例,并非真实接口地址。 | |
| 125 | - complete: () => {}, | |
| 126 | - }); | |
| 127 | - uni.onSocketOpen((header) => { | |
| 128 | - socketTask.send({ | |
| 129 | - data: JSON.stringify({ | |
| 130 | - attrSubCmds: [], | |
| 131 | - tsSubCmds: [{ | |
| 132 | - entityType: "DEVICE", | |
| 133 | - entityId: tbDeviceId, | |
| 134 | - scope: "LATEST_TELEMETRY", | |
| 135 | - cmdId: 1, | |
| 136 | - keys: this.attrList.join(','), | |
| 137 | - }, ], | |
| 138 | - historyCmds: [], | |
| 139 | - entityDataCmds: [], | |
| 140 | - entityDataUnsubscribeCmds: [], | |
| 141 | - alarmDataCmds: [], | |
| 142 | - alarmDataUnsubscribeCmds: [], | |
| 143 | - entityCountCmds: [], | |
| 144 | - entityCountUnsubscribeCmds: [], | |
| 145 | - }), | |
| 146 | - success() {}, | |
| 147 | - }); | |
| 148 | - }); | |
| 149 | - socketTask.onMessage((msg) => { | |
| 150 | - const { | |
| 151 | - data | |
| 152 | - } = JSON.parse(msg.data); | |
| 153 | - const newArray = []; | |
| 154 | - for (const key in data) { | |
| 155 | - const [time, value] = data[key].flat(1); | |
| 156 | - let obj = { | |
| 157 | - key, | |
| 158 | - time, | |
| 159 | - value, | |
| 160 | - }; | |
| 161 | - if (this.recordList.length === 0) { | |
| 162 | - this.recordList.unshift(obj); | |
| 163 | - } else { | |
| 164 | - newArray.push(obj); | |
| 165 | - } | |
| 166 | - } | |
| 167 | - newArray.forEach((item) => { | |
| 168 | - let flag = false; | |
| 169 | - this.recordList.forEach((item1) => { | |
| 170 | - if (item1.key === item.key) { | |
| 171 | - item1.value = item.value; | |
| 172 | - item1.time = item.time; | |
| 173 | - flag = true; | |
| 174 | - } | |
| 175 | - }); | |
| 176 | - if (!flag) { | |
| 177 | - this.recordList.unshift(item); | |
| 178 | - } | |
| 179 | - }); | |
| 180 | - this.recordList = this.recordList.map((item) => { | |
| 181 | - return { | |
| 182 | - ...item, | |
| 183 | - time: formatToDate(item.time, "YYYY-MM-DD HH:mm:ss"), | |
| 184 | - }; | |
| 185 | - }); | |
| 186 | - }); | |
| 187 | - | |
| 188 | - const keys = await getDeviceKeys(tbDeviceId); | |
| 189 | - this.keys = [keys]; | |
| 190 | - // 昨天 | |
| 191 | - this.yesterday = moment().subtract(1, "days").format("YYYY-MM-DD"); | |
| 192 | - // 今天 | |
| 193 | - this.today = moment().format("YYYY-MM-DD"); | |
| 194 | - // 开始时间 | |
| 195 | - this.startTs = moment().subtract(1, "days").format("x"); | |
| 196 | - // 结束时间 | |
| 197 | - this.endTs = moment().format("x"); | |
| 198 | - this.entityId = tbDeviceId; | |
| 199 | - | |
| 200 | - const data = await getHistoryData({ | |
| 201 | - entityId: tbDeviceId, | |
| 202 | - startTs: this.startTs, | |
| 203 | - endTs: this.endTs, | |
| 204 | - keys: keys[0], | |
| 205 | - // interval: 1800000, | |
| 206 | - limit: 7, | |
| 207 | - agg: 'NONE' | |
| 208 | - }); | |
| 209 | - this.timeDiff = "30分钟"; | |
| 210 | - if (!Object.keys(data).length) return; | |
| 211 | - | |
| 212 | - this.historyData = data[keys[0]].map((item) => { | |
| 213 | - return { | |
| 214 | - value: item.value, | |
| 215 | - ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"), | |
| 216 | - }; | |
| 217 | - }); | |
| 218 | - }, | |
| 219 | - methods: { | |
| 220 | - handleTabClick({ | |
| 221 | - index | |
| 222 | - }) { | |
| 223 | - this.currentTab = index; | |
| 224 | - }, | |
| 225 | - handleUpdate(data, e) { | |
| 226 | - if (!Array.isArray(data)) { | |
| 227 | - this.historyData = []; | |
| 228 | - return; | |
| 229 | - } | |
| 230 | - this.historyData = data.map((item) => { | |
| 231 | - return { | |
| 232 | - value: item.value, | |
| 233 | - ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"), | |
| 234 | - }; | |
| 235 | - }); | |
| 236 | - }, | |
| 237 | - }, | |
| 238 | - }; | |
| 239 | -</script> | |
| 240 | - | |
| 241 | -<style lang="scss" scoped> | |
| 242 | - .device-detail-page { | |
| 243 | - height: 100vh; | |
| 244 | - background-color: #f8f9fa; | |
| 245 | - } | |
| 246 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="device-detail-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <u-sticky :bgColor="bgColor"> | |
| 6 | + <u-tabs :list="list" :current="currentTab" @click="handleTabClick" :activeStyle="activeColor" | |
| 7 | + :inactiveStyle="inActiveColor" :scrollable="isScrollable" /> | |
| 8 | + </u-sticky> | |
| 9 | + <view class="mt-3"> | |
| 10 | + <basic-info v-show="currentTab == 0" :deviceDetail="deviceDetail" /> | |
| 11 | + <realtime-data v-show="currentTab === 1" :recordList="recordList" /> | |
| 12 | + <history-data v-if="currentTab === 2" :keys="keys" :yesterday="yesterday" :today="today" | |
| 13 | + :timeDiff="timeDiff" :historyData="historyData" :entityId="entityId" :start="startTs" :end="endTs" | |
| 14 | + @update="handleUpdate" /> | |
| 15 | + <alarm-history v-show="currentTab === 3" :deviceId="deviceId" /> | |
| 16 | + <commond-record v-if="currentTab === 4" :tbDeviceId="entityId" /> | |
| 17 | + </view> | |
| 18 | + </view> | |
| 19 | +</template> | |
| 20 | + | |
| 21 | +<script> | |
| 22 | + import fTabbar from "@/components/module/f-tabbar/f-tabbar"; | |
| 23 | + import basicInfo from "./components/basic-info.vue"; | |
| 24 | + import realtimeData from "./components/realtime-data.vue"; | |
| 25 | + import alarmHistory from "./components/alarm-history.vue"; | |
| 26 | + import historyData from "./components/history-data.vue"; | |
| 27 | + import commondRecord from "./components/command-record.vue"; | |
| 28 | + import { getDeviceKeys,getHistoryData } from "./api/index.js"; | |
| 29 | + import {formatToDate} from "@/plugins/utils.js"; | |
| 30 | + import MescrollCompMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js"; | |
| 31 | + import moment from "moment"; | |
| 32 | + import base from "@/config/baseUrl.js"; | |
| 33 | + import { list } from './config/data.js' | |
| 34 | + import api from '@/api' | |
| 35 | + | |
| 36 | + export default { | |
| 37 | + mixins: [MescrollCompMixin], | |
| 38 | + components: { | |
| 39 | + fTabbar, | |
| 40 | + basicInfo, | |
| 41 | + realtimeData, | |
| 42 | + alarmHistory, | |
| 43 | + historyData, | |
| 44 | + commondRecord, | |
| 45 | + }, | |
| 46 | + data() { | |
| 47 | + return { | |
| 48 | + bgColor: '#fff', | |
| 49 | + activeColor: { | |
| 50 | + fontWeight: 'bold', | |
| 51 | + color: '#333', | |
| 52 | + }, | |
| 53 | + inActiveColor: { | |
| 54 | + color: '#999', | |
| 55 | + }, | |
| 56 | + list, | |
| 57 | + currentTab: 0, | |
| 58 | + deviceId: "", | |
| 59 | + deviceDetail: {}, | |
| 60 | + keys: [], | |
| 61 | + yesterday: "", | |
| 62 | + today: "", | |
| 63 | + timeDiff: "", | |
| 64 | + historyData: [], | |
| 65 | + entityId: "", | |
| 66 | + startTs: "", | |
| 67 | + endTs: "", | |
| 68 | + recordList: [], //实时数据 | |
| 69 | + isScrollable: false, | |
| 70 | + attrList: [] | |
| 71 | + }; | |
| 72 | + }, | |
| 73 | + onUnload() { | |
| 74 | + // 页面关闭时,销毁webSocket连接,否则第二次会存在连接不到的情况 | |
| 75 | + uni.closeSocket(); | |
| 76 | + }, | |
| 77 | + async onLoad(options) { | |
| 78 | + const {id,alarmStatus,lastOnlineTime,tbDeviceId,deviceProfileId} = options; | |
| 79 | + this.deviceId = id; | |
| 80 | + const res = await api.deviceApi.getDeviceDetail(this.deviceId) | |
| 81 | + if(!res) return | |
| 82 | + this.deviceDetail = { | |
| 83 | + ...res, | |
| 84 | + alarmStatus, | |
| 85 | + lastOnlineTime, | |
| 86 | + }; | |
| 87 | + // 设备类型不是网关子设备的添加一个命令记录的选项卡 | |
| 88 | + if (this.deviceDetail.deviceType !== "SENSOR") { | |
| 89 | + this.list.push({ | |
| 90 | + name: "命令记录", | |
| 91 | + }); | |
| 92 | + const res = new Map() | |
| 93 | + this.list = this.list.filter((item) => !res.has(item.name) && res.set(item.name, 1)) | |
| 94 | + } else { | |
| 95 | + this.list = this.list.filter(item => item.name !=='命令记录') | |
| 96 | + } | |
| 97 | + this.isScrollable = this.list.length > 4; | |
| 98 | + if (res.deviceProfileId) { | |
| 99 | + const getAttrList = await api.deviceApi.getAttribute(res.deviceProfileId) | |
| 100 | + if (Array.isArray(getAttrList)) { | |
| 101 | + this.attrList = getAttrList.map(m => { | |
| 102 | + return m.identifier | |
| 103 | + }) | |
| 104 | + } | |
| 105 | + } | |
| 106 | + // 连接webSockte | |
| 107 | + const socketTask = uni.connectSocket({ | |
| 108 | + url: `${base.socketPrefix}://${base.baseWebSocketUrl}/api/ws/plugins/telemetry?token=` + uni.getStorageSync("userInfo").isToken, //仅为示例,并非真实接口地址。 | |
| 109 | + complete: () => {}, | |
| 110 | + }); | |
| 111 | + uni.onSocketOpen((header) => { | |
| 112 | + socketTask.send({ | |
| 113 | + data: JSON.stringify({ | |
| 114 | + attrSubCmds: [], | |
| 115 | + tsSubCmds: [{ | |
| 116 | + entityType: "DEVICE", | |
| 117 | + entityId: tbDeviceId, | |
| 118 | + scope: "LATEST_TELEMETRY", | |
| 119 | + cmdId: 1, | |
| 120 | + keys: this.attrList.join(','), | |
| 121 | + }, ], | |
| 122 | + historyCmds: [], | |
| 123 | + entityDataCmds: [], | |
| 124 | + entityDataUnsubscribeCmds: [], | |
| 125 | + alarmDataCmds: [], | |
| 126 | + alarmDataUnsubscribeCmds: [], | |
| 127 | + entityCountCmds: [], | |
| 128 | + entityCountUnsubscribeCmds: [], | |
| 129 | + }), | |
| 130 | + success() {}, | |
| 131 | + }); | |
| 132 | + }); | |
| 133 | + socketTask.onMessage((msg) => { | |
| 134 | + const { data } = JSON.parse(msg.data); | |
| 135 | + const newArray = []; | |
| 136 | + for (const key in data) { | |
| 137 | + const [time, value] = data[key].flat(1); | |
| 138 | + let obj = { key,time,value, }; | |
| 139 | + if (this.recordList.length === 0) { | |
| 140 | + this.recordList.unshift(obj); | |
| 141 | + } else { | |
| 142 | + newArray.push(obj); | |
| 143 | + } | |
| 144 | + } | |
| 145 | + newArray.forEach((item) => { | |
| 146 | + let flag = false; | |
| 147 | + this.recordList.forEach((item1) => { | |
| 148 | + if (item1.key === item.key) { | |
| 149 | + item1.value = item.value; | |
| 150 | + item1.time = item.time; | |
| 151 | + flag = true; | |
| 152 | + } | |
| 153 | + }); | |
| 154 | + if (!flag) { | |
| 155 | + this.recordList.unshift(item); | |
| 156 | + } | |
| 157 | + }); | |
| 158 | + this.recordList = this.recordList.map((item) => { | |
| 159 | + return { | |
| 160 | + ...item, | |
| 161 | + time: formatToDate(item.time, "YYYY-MM-DD HH:mm:ss"), | |
| 162 | + }; | |
| 163 | + }); | |
| 164 | + }); | |
| 165 | + const keys = await getDeviceKeys(tbDeviceId); | |
| 166 | + this.keys = [keys]; | |
| 167 | + // 昨天 | |
| 168 | + this.yesterday = moment().subtract(1, "days").format("YYYY-MM-DD"); | |
| 169 | + // 今天 | |
| 170 | + this.today = moment().format("YYYY-MM-DD"); | |
| 171 | + // 开始时间 | |
| 172 | + this.startTs = moment().subtract(1, "days").format("x"); | |
| 173 | + // 结束时间 | |
| 174 | + this.endTs = moment().format("x"); | |
| 175 | + this.entityId = tbDeviceId; | |
| 176 | + const data = await getHistoryData({ | |
| 177 | + entityId: tbDeviceId, | |
| 178 | + startTs: this.startTs, | |
| 179 | + endTs: this.endTs, | |
| 180 | + keys: keys[0], | |
| 181 | + // interval: 1800000, | |
| 182 | + limit: 7, | |
| 183 | + agg: 'NONE' | |
| 184 | + }); | |
| 185 | + this.timeDiff = "30分钟"; | |
| 186 | + if (!Object.keys(data).length) return; | |
| 187 | + this.historyData = data[keys[0]].map((item) => { | |
| 188 | + return { | |
| 189 | + value: item.value, | |
| 190 | + ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"), | |
| 191 | + }; | |
| 192 | + }); | |
| 193 | + }, | |
| 194 | + methods: { | |
| 195 | + handleTabClick({ | |
| 196 | + index | |
| 197 | + }) { | |
| 198 | + this.currentTab = index; | |
| 199 | + }, | |
| 200 | + handleUpdate(data, e) { | |
| 201 | + if (!Array.isArray(data)) { | |
| 202 | + this.historyData = []; | |
| 203 | + return; | |
| 204 | + } | |
| 205 | + this.historyData = data.map((item) => { | |
| 206 | + return { | |
| 207 | + value: item.value, | |
| 208 | + ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"), | |
| 209 | + }; | |
| 210 | + }); | |
| 211 | + }, | |
| 212 | + }, | |
| 213 | + }; | |
| 214 | +</script> | |
| 215 | + | |
| 216 | +<style lang="scss" scoped> | |
| 217 | + .device-detail-page { | |
| 218 | + height: 100vh; | |
| 219 | + background-color: #f8f9fa; | |
| 220 | + } | |
| 221 | +</style> | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/device-position.vue
renamed from
deviceSubPage/deviceDetailPage/devicePosition.vue
| 1 | +.command-detail { | |
| 2 | + padding: 5rpx 30rpx; | |
| 3 | + height: 100vh; | |
| 4 | + background-color: #f8f9fa; | |
| 5 | + | |
| 6 | + .detail-top { | |
| 7 | + height: 118rpx; | |
| 8 | + width: 690rpx; | |
| 9 | + display: flex; | |
| 10 | + align-items: center; | |
| 11 | + background-color: #fff; | |
| 12 | + color: #333; | |
| 13 | + border-radius: 20rpx; | |
| 14 | + font-size: 15px; | |
| 15 | + margin-top: 30rpx; | |
| 16 | + padding: 30rpx; | |
| 17 | + } | |
| 18 | + | |
| 19 | + .detail { | |
| 20 | + background-color: #fff; | |
| 21 | + margin-top: 30rpx; | |
| 22 | + border-radius: 20rpx; | |
| 23 | + width: 690rpx; | |
| 24 | + | |
| 25 | + .detail-item { | |
| 26 | + padding: 30rpx; | |
| 27 | + display: flex; | |
| 28 | + align-items: center; | |
| 29 | + | |
| 30 | + .detail-label { | |
| 31 | + color: #333; | |
| 32 | + font-size: 15px; | |
| 33 | + } | |
| 34 | + | |
| 35 | + .detail-value { | |
| 36 | + color: #666; | |
| 37 | + font-size: 14px; | |
| 38 | + margin-left: 30rpx; | |
| 39 | + } | |
| 40 | + } | |
| 41 | + } | |
| 42 | + | |
| 43 | + .command { | |
| 44 | + margin: 30rpx 0; | |
| 45 | + } | |
| 46 | + } | |
| \ No newline at end of file | ... | ... |
| 1 | +.command-record { | |
| 2 | + padding: 0 30rpx; | |
| 3 | + background: #f8f9fa; | |
| 4 | + | |
| 5 | + .filter-button { | |
| 6 | + font-size: 12px; | |
| 7 | + width: 160rpx; | |
| 8 | + height: 64rpx; | |
| 9 | + border-radius: 32rpx; | |
| 10 | + display: flex; | |
| 11 | + justify-content: center; | |
| 12 | + align-items: center; | |
| 13 | + background: #f0f1f2; | |
| 14 | + color: #666; | |
| 15 | + | |
| 16 | + image { | |
| 17 | + width: 28rpx; | |
| 18 | + height: 28rpx; | |
| 19 | + margin-left: 4rpx; | |
| 20 | + } | |
| 21 | + } | |
| 22 | + } | |
| 23 | + | |
| 24 | + .list-item { | |
| 25 | + width: 690rpx; | |
| 26 | + background-color: #fff; | |
| 27 | + border-radius: 20rpx; | |
| 28 | + margin: 20rpx auto; | |
| 29 | + color: #333; | |
| 30 | + | |
| 31 | + .item { | |
| 32 | + .delivered-color { | |
| 33 | + color: blue; | |
| 34 | + } | |
| 35 | + | |
| 36 | + padding: 30rpx; | |
| 37 | + | |
| 38 | + view { | |
| 39 | + font-size: 14px; | |
| 40 | + margin-bottom: 10rpx; | |
| 41 | + } | |
| 42 | + | |
| 43 | + .time { | |
| 44 | + margin-top: 20rpx; | |
| 45 | + color: #999; | |
| 46 | + } | |
| 47 | + | |
| 48 | + .item-first { | |
| 49 | + display: flex; | |
| 50 | + justify-content: space-between; | |
| 51 | + align-items: center; | |
| 52 | + font-size: 15px; | |
| 53 | + font-weight: 500; | |
| 54 | + align-items: center; | |
| 55 | + | |
| 56 | + .item-right { | |
| 57 | + display: flex; | |
| 58 | + justify-content: center; | |
| 59 | + align-items: center; | |
| 60 | + width: 104rpx; | |
| 61 | + height: 36rpx; | |
| 62 | + font-size: 10px; | |
| 63 | + border-radius: 20rpx; | |
| 64 | + } | |
| 65 | + | |
| 66 | + .item-fail { | |
| 67 | + color: #848383; | |
| 68 | + background-color: #84838325; | |
| 69 | + } | |
| 70 | + | |
| 71 | + .item.success { | |
| 72 | + color: #00c9a7; | |
| 73 | + background-color: #00c9a725; | |
| 74 | + } | |
| 75 | + } | |
| 76 | + } | |
| 77 | + } | |
| 78 | + | |
| 79 | + .filter { | |
| 80 | + padding: 0 30rpx; | |
| 81 | + | |
| 82 | + .filter-title { | |
| 83 | + text-align: center; | |
| 84 | + margin-top: 14px; | |
| 85 | + font-size: 16px; | |
| 86 | + font-weight: 700; | |
| 87 | + } | |
| 88 | + | |
| 89 | + .button-group { | |
| 90 | + display: flex; | |
| 91 | + margin-top: 40rpx; | |
| 92 | + justify-content: space-between; | |
| 93 | + | |
| 94 | + view { | |
| 95 | + width: 330rpx; | |
| 96 | + } | |
| 97 | + } | |
| 98 | + | |
| 99 | + .command-time-text { | |
| 100 | + color: #333; | |
| 101 | + font-size: 14px; | |
| 102 | + font-weight: 700; | |
| 103 | + } | |
| 104 | + } | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/static/modal.css
renamed from
deviceSubPage/deviceDetailPage/styles/modal.css
| 1 | +/* ================== | |
| 2 | +模态窗口 采用colorsui的部分样式 | |
| 3 | +==================== */ | |
| 4 | + | |
| 1 | 5 | .cu-modal { |
| 2 | 6 | position: fixed; |
| 3 | 7 | top: 0; |
| ... | ... | @@ -18,7 +22,7 @@ |
| 18 | 22 | } |
| 19 | 23 | |
| 20 | 24 | .cu-modal::before { |
| 21 | - content: "\200B"; | |
| 25 | + content: '\200B'; | |
| 22 | 26 | display: inline-block; |
| 23 | 27 | height: 100%; |
| 24 | 28 | vertical-align: middle; |
| ... | ... | @@ -89,8 +93,8 @@ |
| 89 | 93 | transform: translateX(0%); |
| 90 | 94 | } |
| 91 | 95 | |
| 92 | -.cu-modal .cu-dialog>.cu-bar:first-child .action { | |
| 96 | +.cu-modal .cu-dialog > .cu-bar:first-child .action { | |
| 93 | 97 | min-width: 100rpx; |
| 94 | 98 | margin-right: 0; |
| 95 | 99 | min-height: 100rpx; |
| 96 | -} | |
| 100 | +} | |
| \ No newline at end of file | ... | ... |
device-subpackage/device-detail/static/realtime-data.scss
renamed from
deviceSubPage/deviceDetailPage/tabDetail/realtimeData.vue
| 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 class="item-value">{{ item.value }}</view> | |
| 7 | - </view> | |
| 8 | - <view class="item-time">{{ item.time }}</view> | |
| 9 | - </view> | |
| 10 | - <mescroll-empty v-if="!recordList.length" /> | |
| 11 | - </view> | |
| 12 | -</template> | |
| 13 | - | |
| 14 | -<script> | |
| 15 | -export default { | |
| 16 | - props: { | |
| 17 | - recordList: { | |
| 18 | - type: Array, | |
| 19 | - default: () => [] | |
| 20 | - } | |
| 21 | - } | |
| 22 | -}; | |
| 23 | -</script> | |
| 24 | - | |
| 25 | -<style lang="scss" scoped> | |
| 26 | -.realtime-page { | |
| 27 | - .item { | |
| 28 | - margin: 30rpx; | |
| 29 | - padding: 30rpx; | |
| 30 | - border-radius: 20rpx; | |
| 31 | - background-color: #fff; | |
| 32 | - height: 160rpx; | |
| 33 | - width: 690rpx; | |
| 34 | - .item-top { | |
| 35 | - display: flex; | |
| 36 | - justify-content: space-between; | |
| 37 | - color: #333; | |
| 38 | - font-size: 16px; | |
| 39 | - font-family: PingFangSC-Medium, PingFang SC; | |
| 40 | - font-weight: bold; | |
| 41 | - .item-value { | |
| 42 | - font-weight: bold; | |
| 43 | - } | |
| 44 | - } | |
| 45 | - .item-time { | |
| 46 | - margin-top: 4rpx; | |
| 47 | - font-size: 13px; | |
| 48 | - color: #999; | |
| 49 | - } | |
| 50 | - } | |
| 51 | -} | |
| 52 | -</style> | |
| 1 | +.realtime-page { | |
| 2 | + .item { | |
| 3 | + margin: 30rpx; | |
| 4 | + padding: 30rpx; | |
| 5 | + border-radius: 20rpx; | |
| 6 | + background-color: #fff; | |
| 7 | + height: 160rpx; | |
| 8 | + width: 690rpx; | |
| 9 | + .item-top { | |
| 10 | + display: flex; | |
| 11 | + justify-content: space-between; | |
| 12 | + color: #333; | |
| 13 | + font-size: 16px; | |
| 14 | + font-family: PingFangSC-Medium, PingFang SC; | |
| 15 | + font-weight: bold; | |
| 16 | + .item-value { | |
| 17 | + font-weight: bold; | |
| 18 | + } | |
| 19 | + } | |
| 20 | + .item-time { | |
| 21 | + margin-top: 4rpx; | |
| 22 | + font-size: 13px; | |
| 23 | + color: #999; | |
| 24 | + } | |
| 25 | + } | |
| 26 | +} | |
| \ No newline at end of file | ... | ... |
deviceSubPage/deviceDetailPage/tabDetail/CommandRecord.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <!-- 单向没有响应失败状态 --> | |
| 3 | - <!-- 响应类型 --> | |
| 4 | - <view class="command-record"> | |
| 5 | - <view class="filter-button" @click="openSearchDialog"> | |
| 6 | - <text>筛选</text> | |
| 7 | - <image src="../../../static/shaixuan.png" /> | |
| 8 | - </view> | |
| 9 | - | |
| 10 | - <mescroll-uni ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback" | |
| 11 | - height="700px"> | |
| 12 | - <view @click="openCommandDetail(item)" class="list-item" v-for="(item, index) in list" :key="index"> | |
| 13 | - <view class="item"> | |
| 14 | - <view class="item-first"> | |
| 15 | - <text>{{ item.deviceName }}</text> | |
| 16 | - <view v-if="!item.request.oneway"> | |
| 17 | - <view class="item-right item-success" v-if="item.response">响应成功</view> | |
| 18 | - <view class="item-right item-fail" v-else>响应失败</view> | |
| 19 | - </view> | |
| 20 | - </view> | |
| 21 | - <view> | |
| 22 | - 命令类型: | |
| 23 | - <text style="margin-left: 16rpx;">{{ item.additionalInfo.cmdType===1?'服务':'自定义' }}</text> | |
| 24 | - </view> | |
| 25 | - <view v-if="item.statusName"> | |
| 26 | - 命令状态: | |
| 27 | - <text :style="{ | |
| 28 | - color: | |
| 29 | - item.status == 'EXPIRED' | |
| 30 | - ? 'red' | |
| 31 | - : item.status == 'DELIVERED' | |
| 32 | - ? 'blue' | |
| 33 | - : item.status == 'QUEUED' | |
| 34 | - ? '#00C9A7' | |
| 35 | - : item.status == 'TIMEOUT' | |
| 36 | - ? 'red' | |
| 37 | - : item.status == 'SENT' | |
| 38 | - ? '#00C9A7' | |
| 39 | - : '' | |
| 40 | - }" style="margin-left: 16rpx;"> | |
| 41 | - {{ item.statusName }} | |
| 42 | - </text> | |
| 43 | - </view> | |
| 44 | - <view class="item-first"> | |
| 45 | - <view> | |
| 46 | - 响应类型: | |
| 47 | - <text style="margin-left: 16rpx;">{{ !item.request.oneway?'双向':'单向' }}</text> | |
| 48 | - </view> | |
| 49 | - <view class="time">{{ format(item.createTime) }}</view> | |
| 50 | - </view> | |
| 51 | - </view> | |
| 52 | - </view> | |
| 53 | - </mescroll-uni> | |
| 54 | - <!-- 告警筛选 --> | |
| 55 | - <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20" | |
| 56 | - @touchmove.stop.prevent="disabledScroll"> | |
| 57 | - <view class="filter" @touchmove.stop.prevent="disabledScroll"> | |
| 58 | - <view class="filter-title"><text>筛选条件</text></view> | |
| 59 | - <FilterItem :filterList="issueStatus" title="下发状态" | |
| 60 | - @clickTag="currentIndex => handleClickTag(currentIndex, issueStatus)"></FilterItem> | |
| 61 | - <view class="button-group"> | |
| 62 | - <view> | |
| 63 | - <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" | |
| 64 | - @click="resetFilter"></u-button> | |
| 65 | - </view> | |
| 66 | - <view> | |
| 67 | - <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button> | |
| 68 | - </view> | |
| 69 | - </view> | |
| 70 | - </view> | |
| 71 | - </u-popup> | |
| 72 | - <u-calendar :show="showCalendar" mode="range" @confirm="calendarConfirm" @close="calendarClose" startText="开始时间" | |
| 73 | - endText="结束时间" confirmDisabledText="请选择日期" :formatter="formatter"></u-calendar> | |
| 74 | - </view> | |
| 75 | -</template> | |
| 76 | -<script> | |
| 77 | - import FilterItem from '@/pages/device/FilterItem.vue'; | |
| 78 | - import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 79 | - import { | |
| 80 | - formatToDate | |
| 81 | - } from '@/plugins/utils.js'; | |
| 82 | - import { | |
| 83 | - debounce | |
| 84 | - } from '@/plugins/throttle.js'; | |
| 85 | - export default { | |
| 86 | - mixins: [MescrollMixin], | |
| 87 | - components: { | |
| 88 | - FilterItem | |
| 89 | - }, | |
| 90 | - props: { | |
| 91 | - tbDeviceId: { | |
| 92 | - type: String, | |
| 93 | - default: '' | |
| 94 | - } | |
| 95 | - }, | |
| 96 | - data() { | |
| 97 | - return { | |
| 98 | - show: false, | |
| 99 | - list: [], | |
| 100 | - total: '', | |
| 101 | - timeData: { | |
| 102 | - selectTime: '', | |
| 103 | - getTimeGap: '' | |
| 104 | - }, | |
| 105 | - showCalendar: false, | |
| 106 | - issueStatus: [{ | |
| 107 | - checked: true, | |
| 108 | - name: '全部', | |
| 109 | - type: '' | |
| 110 | - }, | |
| 111 | - { | |
| 112 | - checked: false, | |
| 113 | - name: '响应成功', | |
| 114 | - type: 'SUCCESSFUL' | |
| 115 | - }, | |
| 116 | - { | |
| 117 | - checked: false, | |
| 118 | - name: '发送成功', | |
| 119 | - type: 'DELIVERED' | |
| 120 | - }, | |
| 121 | - { | |
| 122 | - checked: false, | |
| 123 | - name: '已过期', | |
| 124 | - type: 'EXPIRED' | |
| 125 | - }, | |
| 126 | - { | |
| 127 | - checked: false, | |
| 128 | - name: '响应失败', | |
| 129 | - type: 'FAILED' | |
| 130 | - } | |
| 131 | - ], | |
| 132 | - downOption: { | |
| 133 | - auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 134 | - }, | |
| 135 | - page: { | |
| 136 | - num: 0, | |
| 137 | - size: 10 | |
| 138 | - } | |
| 139 | - }; | |
| 140 | - }, | |
| 141 | - methods: { | |
| 142 | - /*下拉刷新的回调 */ | |
| 143 | - downCallback() { | |
| 144 | - //联网加载数据 | |
| 145 | - this.list = []; | |
| 146 | - this.page.num = 1; | |
| 147 | - this.loadData(this.page.num, { | |
| 148 | - tbDeviceId: this.tbDeviceId | |
| 149 | - }); | |
| 150 | - }, | |
| 151 | - format(date) { | |
| 152 | - return formatToDate(date, 'YYYY-MM-DD HH:mm:ss'); | |
| 153 | - }, | |
| 154 | - disabledScroll() { | |
| 155 | - return; | |
| 156 | - }, | |
| 157 | - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 158 | - upCallback() { | |
| 159 | - //联网加载数据 | |
| 160 | - this.page.num += 1; | |
| 161 | - this.loadData(this.page.num, { | |
| 162 | - tbDeviceId: this.tbDeviceId | |
| 163 | - }); | |
| 164 | - }, | |
| 165 | - //获取告警数据 | |
| 166 | - loadData(pageNo, params = {}) { | |
| 167 | - let httpData = { | |
| 168 | - ...params, | |
| 169 | - page: pageNo, | |
| 170 | - pageSize: 10 | |
| 171 | - }; | |
| 172 | - uni.$u.http | |
| 173 | - .get('/yt/rpc', { | |
| 174 | - params: httpData, | |
| 175 | - custom: { | |
| 176 | - load: false | |
| 177 | - } | |
| 178 | - }) | |
| 179 | - .then(res => { | |
| 180 | - this.total = res.total; | |
| 181 | - uni.stopPullDownRefresh(); | |
| 182 | - //方法一(推荐): 后台接口有返回列表的总页数 totalPage | |
| 183 | - this.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数) | |
| 184 | - if (pageNo == 1) { | |
| 185 | - this.list = res.items; | |
| 186 | - } else { | |
| 187 | - this.list = this.list.concat(res.items); | |
| 188 | - } | |
| 189 | - }) | |
| 190 | - .catch(() => { | |
| 191 | - //联网失败, 结束加载 | |
| 192 | - this.mescroll.endErr(); | |
| 193 | - }); | |
| 194 | - }, | |
| 195 | - handleClickTag(currentIndex, list) { | |
| 196 | - list.map((item, index) => { | |
| 197 | - item.checked = index === currentIndex; | |
| 198 | - }); | |
| 199 | - }, | |
| 200 | - resetFilter() { | |
| 201 | - const { | |
| 202 | - issueStatus | |
| 203 | - } = this; | |
| 204 | - issueStatus.forEach(item => item.map((item, index) => (item.checked = index === 0))); | |
| 205 | - }, | |
| 206 | - close() { | |
| 207 | - this.show = false; | |
| 208 | - }, | |
| 209 | - openSearchDialog() { | |
| 210 | - this.show = true; | |
| 211 | - }, | |
| 212 | - hideKeyboard() { | |
| 213 | - uni.hideKeyboard(); | |
| 214 | - }, | |
| 215 | - calendarConfirm(e) { | |
| 216 | - this.showCalendar = false; | |
| 217 | - this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`; | |
| 218 | - }, | |
| 219 | - confirmFilter() { | |
| 220 | - const issueStatus = this.issueStatus.find(item => item.checked); | |
| 221 | - this.loadData(1, { | |
| 222 | - status: issueStatus.type ? issueStatus.type : undefined, | |
| 223 | - tbDeviceId: this.tbDeviceId | |
| 224 | - }); | |
| 225 | - this.show = false; | |
| 226 | - }, | |
| 227 | - calendarClose() { | |
| 228 | - this.showCalendar = false; | |
| 229 | - }, | |
| 230 | - openCommandDetail(item) { | |
| 231 | - uni.navigateTo({ | |
| 232 | - url: '/deviceSubPage/deviceDetailPage/tabDetail/CommandDetail?data=' + JSON.stringify(item) | |
| 233 | - }); | |
| 234 | - } | |
| 235 | - } | |
| 236 | - }; | |
| 237 | -</script> | |
| 238 | - | |
| 239 | -<style lang="scss" scoped> | |
| 240 | - .command-record { | |
| 241 | - padding: 0 30rpx; | |
| 242 | - background: #f8f9fa; | |
| 243 | - | |
| 244 | - .filter-button { | |
| 245 | - font-size: 12px; | |
| 246 | - width: 160rpx; | |
| 247 | - height: 64rpx; | |
| 248 | - border-radius: 32rpx; | |
| 249 | - display: flex; | |
| 250 | - justify-content: center; | |
| 251 | - align-items: center; | |
| 252 | - background: #f0f1f2; | |
| 253 | - color: #666; | |
| 254 | - | |
| 255 | - image { | |
| 256 | - width: 28rpx; | |
| 257 | - height: 28rpx; | |
| 258 | - margin-left: 4rpx; | |
| 259 | - } | |
| 260 | - } | |
| 261 | - } | |
| 262 | - | |
| 263 | - .list-item { | |
| 264 | - width: 690rpx; | |
| 265 | - background-color: #fff; | |
| 266 | - border-radius: 20rpx; | |
| 267 | - margin: 20rpx auto; | |
| 268 | - color: #333; | |
| 269 | - | |
| 270 | - .item { | |
| 271 | - .delivered-color { | |
| 272 | - color: blue; | |
| 273 | - } | |
| 274 | - | |
| 275 | - padding: 30rpx; | |
| 276 | - | |
| 277 | - view { | |
| 278 | - font-size: 14px; | |
| 279 | - margin-bottom: 10rpx; | |
| 280 | - } | |
| 281 | - | |
| 282 | - .time { | |
| 283 | - margin-top: 20rpx; | |
| 284 | - color: #999; | |
| 285 | - } | |
| 286 | - | |
| 287 | - .item-first { | |
| 288 | - display: flex; | |
| 289 | - justify-content: space-between; | |
| 290 | - align-items: center; | |
| 291 | - font-size: 15px; | |
| 292 | - font-weight: 500; | |
| 293 | - align-items: center; | |
| 294 | - | |
| 295 | - .item-right { | |
| 296 | - display: flex; | |
| 297 | - justify-content: center; | |
| 298 | - align-items: center; | |
| 299 | - width: 104rpx; | |
| 300 | - height: 36rpx; | |
| 301 | - font-size: 10px; | |
| 302 | - border-radius: 20rpx; | |
| 303 | - } | |
| 304 | - | |
| 305 | - .item-fail { | |
| 306 | - color: #848383; | |
| 307 | - background-color: #84838325; | |
| 308 | - } | |
| 309 | - | |
| 310 | - .item.success { | |
| 311 | - color: #00c9a7; | |
| 312 | - background-color: #00c9a725; | |
| 313 | - } | |
| 314 | - } | |
| 315 | - } | |
| 316 | - } | |
| 317 | - | |
| 318 | - .filter { | |
| 319 | - padding: 0 30rpx; | |
| 320 | - | |
| 321 | - .filter-title { | |
| 322 | - text-align: center; | |
| 323 | - margin-top: 14px; | |
| 324 | - font-size: 16px; | |
| 325 | - font-weight: 700; | |
| 326 | - } | |
| 327 | - | |
| 328 | - .button-group { | |
| 329 | - display: flex; | |
| 330 | - margin-top: 40rpx; | |
| 331 | - justify-content: space-between; | |
| 332 | - | |
| 333 | - view { | |
| 334 | - width: 330rpx; | |
| 335 | - } | |
| 336 | - } | |
| 337 | - } | |
| 338 | -</style> |
deviceSubPage/deviceDetailPage/tabDetail/alarmHistory.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <view class="alert-page"> | |
| 3 | - <view class="filter-button" @click="openSearchDialog"> | |
| 4 | - <text>筛选</text> | |
| 5 | - <image src="../../../static/shaixuan.png" /> | |
| 6 | - </view> | |
| 7 | - | |
| 8 | - <mescroll-uni ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback" height="700px"> | |
| 9 | - <view @click="openDeviceDetail(item)" class="list-item" v-for="(item, index) in list" :key="index"> | |
| 10 | - <view class="item"> | |
| 11 | - <view class="item-first"> | |
| 12 | - <text style="font-weight: bold;">{{ item.deviceName }}</text> | |
| 13 | - <view class="item-right"> | |
| 14 | - <image | |
| 15 | - :src=" | |
| 16 | - item.severity === 'CRITICAL' | |
| 17 | - ? '../../../static/danger.png' | |
| 18 | - : item.severity === 'MAJOR' | |
| 19 | - ? '../../../static/major.png' | |
| 20 | - : item.severity === 'MINOR' | |
| 21 | - ? '../../../static/secondary.png' | |
| 22 | - : item.severity === 'WARNING' | |
| 23 | - ? '../../../static/warn.png' | |
| 24 | - : '../../../static/noshue.png' | |
| 25 | - " | |
| 26 | - ></image> | |
| 27 | - <text | |
| 28 | - :style="{ | |
| 29 | - color: | |
| 30 | - item.severity === 'CRITICAL' | |
| 31 | - ? '#DE4437' | |
| 32 | - : item.severity === 'MAJOR' | |
| 33 | - ? '#DE7337' | |
| 34 | - : item.severity === 'MINOR' | |
| 35 | - ? '#FFC107' | |
| 36 | - : item.severity === 'WARNING' | |
| 37 | - ? '#FF1E0B' | |
| 38 | - : '#00C9A7' | |
| 39 | - }" | |
| 40 | - > | |
| 41 | - {{ | |
| 42 | - item.severity === 'CRITICAL' | |
| 43 | - ? '危险' | |
| 44 | - : item.severity === 'MAJOR' | |
| 45 | - ? '重要' | |
| 46 | - : item.severity === 'MINOR' | |
| 47 | - ? '次要' | |
| 48 | - : item.severity === 'WARNING' | |
| 49 | - ? '警告' | |
| 50 | - : '不确定' | |
| 51 | - }} | |
| 52 | - </text> | |
| 53 | - </view> | |
| 54 | - </view> | |
| 55 | - <view> | |
| 56 | - {{ Object.entries(item.details.data)[0][0] }} : | |
| 57 | - <text style="font-weight: bold; margin-left:4rpx;">{{ Object.entries(item.details.data)[0][1] }}</text> | |
| 58 | - </view> | |
| 59 | - <view v-if="item.status"> | |
| 60 | - 告警状态:{{ | |
| 61 | - item.status === 'CLEARED_UNACK' | |
| 62 | - ? '清除未确认' | |
| 63 | - : item.status === 'CLEARED_ACK' | |
| 64 | - ? '清除已确认' | |
| 65 | - : item.status === 'ACTIVE_UNACK' | |
| 66 | - ? '激活未确认' | |
| 67 | - : '激活已确认' | |
| 68 | - }} | |
| 69 | - </view> | |
| 70 | - <view class="time">{{ item.createdTime }}</view> | |
| 71 | - </view> | |
| 72 | - </view> | |
| 73 | - </mescroll-uni> | |
| 74 | - <!-- 告警筛选 --> | |
| 75 | - <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20" @touchmove.stop.prevent="disabledScroll"> | |
| 76 | - <view class="filter" @touchmove.stop.prevent="disabledScroll"> | |
| 77 | - <view class="filter-title"><text>筛选条件</text></view> | |
| 78 | - <FilterItem :filterList="alarmStatus" title="告警状态" @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem> | |
| 79 | - <FilterItem :filterList="typeStatus" title="设备类型" @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem> | |
| 80 | - <FilterItem :filterList="alarmLevelStatus" title="告警等级" @clickTag="currentIndex => handleClickTag(currentIndex, alarmLevelStatus)"></FilterItem> | |
| 81 | - <FilterItem :filterList="timeStatus" title="选择时间" @clickTag="currentIndex => handleClickTag(currentIndex, timeStatus)"></FilterItem> | |
| 82 | - <view class="button-group"> | |
| 83 | - <view><u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" @click="resetFilter"></u-button></view> | |
| 84 | - <view><u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button></view> | |
| 85 | - </view> | |
| 86 | - </view> | |
| 87 | - </u-popup> | |
| 88 | - <u-calendar | |
| 89 | - :show="showCalendar" | |
| 90 | - mode="range" | |
| 91 | - @confirm="calendarConfirm" | |
| 92 | - @close="calendarClose" | |
| 93 | - startText="开始时间" | |
| 94 | - endText="结束时间" | |
| 95 | - confirmDisabledText="请选择日期" | |
| 96 | - ></u-calendar> | |
| 97 | - </view> | |
| 98 | -</template> | |
| 99 | -<script> | |
| 100 | -import FilterItem from '@/pages/device/FilterItem.vue'; | |
| 101 | -import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 102 | -export default { | |
| 103 | - mixins: [MescrollMixin], | |
| 104 | - components: { | |
| 105 | - FilterItem | |
| 106 | - }, | |
| 107 | - props: { | |
| 108 | - deviceId: { | |
| 109 | - type: String, | |
| 110 | - default: '' | |
| 111 | - } | |
| 112 | - }, | |
| 113 | - data() { | |
| 114 | - return { | |
| 115 | - show: false, | |
| 116 | - list: [], | |
| 117 | - total: '', | |
| 118 | - timeData: { | |
| 119 | - selectTime: '', | |
| 120 | - getTimeGap: '' | |
| 121 | - }, | |
| 122 | - showCalendar: false, | |
| 123 | - alarmStatus: [ | |
| 124 | - { | |
| 125 | - checked: true, | |
| 126 | - name: '全部', | |
| 127 | - type: '' | |
| 128 | - }, | |
| 129 | - { | |
| 130 | - checked: false, | |
| 131 | - name: '激活未确认', | |
| 132 | - type: 'ACTIVE_UNACK' | |
| 133 | - }, | |
| 134 | - { | |
| 135 | - checked: false, | |
| 136 | - name: '激活已确认', | |
| 137 | - type: 'ACTIVE_ACK' | |
| 138 | - }, | |
| 139 | - { | |
| 140 | - checked: false, | |
| 141 | - name: '清除未确认', | |
| 142 | - type: 'CLEARED_UNACK' | |
| 143 | - }, | |
| 144 | - { | |
| 145 | - checked: false, | |
| 146 | - name: '清除已确认', | |
| 147 | - type: 'CLEARED_ACK' | |
| 148 | - } | |
| 149 | - ], | |
| 150 | - typeStatus: [ | |
| 151 | - { | |
| 152 | - checked: true, | |
| 153 | - name: '全部', | |
| 154 | - type: '' | |
| 155 | - }, | |
| 156 | - { | |
| 157 | - checked: false, | |
| 158 | - name: '网关设备', | |
| 159 | - type: 'GATEWAY' | |
| 160 | - }, | |
| 161 | - { | |
| 162 | - checked: false, | |
| 163 | - name: '网关子设备', | |
| 164 | - type: 'SENSOR' | |
| 165 | - }, | |
| 166 | - { | |
| 167 | - checked: false, | |
| 168 | - name: '直连设备', | |
| 169 | - type: 'DIRECT_CONNECTION' | |
| 170 | - } | |
| 171 | - ], | |
| 172 | - alarmLevelStatus: [ | |
| 173 | - { | |
| 174 | - checked: true, | |
| 175 | - name: '全部', | |
| 176 | - type: '' | |
| 177 | - }, | |
| 178 | - { | |
| 179 | - checked: false, | |
| 180 | - name: '危险', | |
| 181 | - type: 'CRITICAL' | |
| 182 | - }, | |
| 183 | - { | |
| 184 | - checked: false, | |
| 185 | - name: '重要', | |
| 186 | - type: 'MAJOR' | |
| 187 | - }, | |
| 188 | - { | |
| 189 | - checked: false, | |
| 190 | - name: '次要', | |
| 191 | - type: 'MINOR' | |
| 192 | - }, | |
| 193 | - { | |
| 194 | - checked: false, | |
| 195 | - name: '警告', | |
| 196 | - type: 'WARNING' | |
| 197 | - }, | |
| 198 | - { | |
| 199 | - checked: false, | |
| 200 | - name: '不确定', | |
| 201 | - type: 'INDETERMINATE' | |
| 202 | - } | |
| 203 | - ], | |
| 204 | - timeStatus: [ | |
| 205 | - { | |
| 206 | - checked: true, | |
| 207 | - name: '全部', | |
| 208 | - type: '' | |
| 209 | - }, | |
| 210 | - { | |
| 211 | - checked: false, | |
| 212 | - name: '30分钟', | |
| 213 | - type: '1800000' | |
| 214 | - }, | |
| 215 | - { | |
| 216 | - checked: false, | |
| 217 | - name: '一小时', | |
| 218 | - type: '3600000' | |
| 219 | - }, | |
| 220 | - { | |
| 221 | - checked: false, | |
| 222 | - name: '2小时', | |
| 223 | - type: '7200000' | |
| 224 | - }, | |
| 225 | - { | |
| 226 | - checked: false, | |
| 227 | - name: '近一天', | |
| 228 | - type: '86400000' | |
| 229 | - } | |
| 230 | - ], | |
| 231 | - downOption: { | |
| 232 | - auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 233 | - }, | |
| 234 | - page: { | |
| 235 | - num: 0, | |
| 236 | - size: 10 | |
| 237 | - } | |
| 238 | - }; | |
| 239 | - }, | |
| 240 | - methods: { | |
| 241 | - disabledScroll() { | |
| 242 | - return; | |
| 243 | - }, | |
| 244 | - /*下拉刷新的回调 */ | |
| 245 | - downCallback() { | |
| 246 | - //联网加载数据 | |
| 247 | - this.list = []; | |
| 248 | - this.page.num = 1; | |
| 249 | - this.loadData(this.page.num, { | |
| 250 | - deviceId: this.deviceId | |
| 251 | - }); | |
| 252 | - }, | |
| 253 | - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 254 | - upCallback() { | |
| 255 | - //联网加载数据 | |
| 256 | - this.page.num += 1; | |
| 257 | - this.loadData(this.page.num, { | |
| 258 | - deviceId: this.deviceId | |
| 259 | - }); | |
| 260 | - }, | |
| 261 | - //获取告警数据 | |
| 262 | - loadData(pageNo, params = {}) { | |
| 263 | - let httpData = { | |
| 264 | - ...params, | |
| 265 | - page: pageNo, | |
| 266 | - pageSize: 10 | |
| 267 | - }; | |
| 268 | - uni.$u.http | |
| 269 | - .get('/yt/alarm', { | |
| 270 | - params: httpData, | |
| 271 | - custom: { | |
| 272 | - load: false | |
| 273 | - } | |
| 274 | - }) | |
| 275 | - .then(res => { | |
| 276 | - this.total = res.total; | |
| 277 | - uni.stopPullDownRefresh(); | |
| 278 | - //方法一(推荐): 后台接口有返回列表的总页数 totalPage | |
| 279 | - this.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数) | |
| 280 | - if (pageNo == 1) { | |
| 281 | - this.list = res.items; | |
| 282 | - } else { | |
| 283 | - this.list = this.list.concat(res.items); | |
| 284 | - } | |
| 285 | - }) | |
| 286 | - .catch(() => { | |
| 287 | - //联网失败, 结束加载 | |
| 288 | - this.mescroll.endErr(); | |
| 289 | - }); | |
| 290 | - }, | |
| 291 | - handleClickTag(currentIndex, list) { | |
| 292 | - list.map((item, index) => { | |
| 293 | - item.checked = index === currentIndex; | |
| 294 | - }); | |
| 295 | - }, | |
| 296 | - resetFilter() { | |
| 297 | - const { alarmStatus, typeStatus, alarmLevelStatus, timeStatus } = this; | |
| 298 | - [alarmStatus, typeStatus, alarmLevelStatus, timeStatus].forEach(item => item.map((item, index) => (item.checked = index === 0))); | |
| 299 | - }, | |
| 300 | - close() { | |
| 301 | - this.show = false; | |
| 302 | - }, | |
| 303 | - openSearchDialog() { | |
| 304 | - this.show = true; | |
| 305 | - }, | |
| 306 | - hideKeyboard() { | |
| 307 | - uni.hideKeyboard(); | |
| 308 | - }, | |
| 309 | - calendarConfirm(e) { | |
| 310 | - this.showCalendar = false; | |
| 311 | - this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`; | |
| 312 | - }, | |
| 313 | - confirmFilter() { | |
| 314 | - const alarmState = this.alarmStatus.find(item => item.checked); | |
| 315 | - const typeState = this.typeStatus.find(item => item.checked); | |
| 316 | - const alarmLevelState = this.alarmLevelStatus.find(item => item.checked); | |
| 317 | - const timeState = this.timeStatus.find(item => item.checked); | |
| 318 | - const endTs = Date.now(); | |
| 319 | - const startTs = endTs - timeState.type; | |
| 320 | - this.loadData(1, { | |
| 321 | - status: alarmState.type ? alarmState.type : undefined, | |
| 322 | - deviceType: typeState.type ? typeState.type : undefined, | |
| 323 | - severity: alarmLevelState.type ? alarmLevelState.type : undefined, | |
| 324 | - startTime: timeState.type ? startTs : undefined, | |
| 325 | - endTime: timeState.type ? endTs : undefined, | |
| 326 | - deviceId: this.deviceId | |
| 327 | - }); | |
| 328 | - this.show = false; | |
| 329 | - }, | |
| 330 | - calendarClose() { | |
| 331 | - this.showCalendar = false; | |
| 332 | - }, | |
| 333 | - openDeviceDetail(item) { | |
| 334 | - const { id, deviceName, severity, originatorType, details, createdTime, status } = item; | |
| 335 | - let obj = { | |
| 336 | - id, | |
| 337 | - deviceName, | |
| 338 | - severity, | |
| 339 | - originatorType, | |
| 340 | - details, | |
| 341 | - createdTime, | |
| 342 | - status | |
| 343 | - }; | |
| 344 | - uni.navigateTo({ | |
| 345 | - url: '/alarmSubPage/alarmDetailPage/alarmDetail?data=' + JSON.stringify(obj) | |
| 346 | - // url: '/' + JSON.stringify(obj) | |
| 347 | - }); | |
| 348 | - } | |
| 349 | - } | |
| 350 | -}; | |
| 351 | -</script> | |
| 352 | - | |
| 353 | -<style lang="scss" scoped> | |
| 354 | -.filter-button { | |
| 355 | - font-size: 12px; | |
| 356 | - width: 160rpx; | |
| 357 | - height: 64rpx; | |
| 358 | - border-radius: 32rpx; | |
| 359 | - display: flex; | |
| 360 | - justify-content: center; | |
| 361 | - align-items: center; | |
| 362 | - background: #f0f1f2; | |
| 363 | - color: #666; | |
| 364 | - image { | |
| 365 | - width: 28rpx; | |
| 366 | - height: 28rpx; | |
| 367 | - margin-left: 4rpx; | |
| 368 | - } | |
| 369 | -} | |
| 370 | -.alert-page { | |
| 371 | - padding: 0 30rpx; | |
| 372 | - .list-item { | |
| 373 | - width: 690rpx; | |
| 374 | - height: 262rpx; | |
| 375 | - background-color: #fff; | |
| 376 | - border-radius: 20rpx; | |
| 377 | - margin: 20rpx auto; | |
| 378 | - color: #333; | |
| 379 | - .item { | |
| 380 | - padding: 30rpx; | |
| 381 | - view { | |
| 382 | - font-size: 14px; | |
| 383 | - margin-bottom: 10rpx; | |
| 384 | - } | |
| 385 | - .time { | |
| 386 | - color: #999; | |
| 387 | - } | |
| 388 | - .item-first { | |
| 389 | - display: flex; | |
| 390 | - justify-content: space-between; | |
| 391 | - font-size: 15px; | |
| 392 | - font-weight: 500; | |
| 393 | - align-items: center; | |
| 394 | - .item-right { | |
| 395 | - display: flex; | |
| 396 | - align-items: center; | |
| 397 | - image { | |
| 398 | - width: 28rpx; | |
| 399 | - height: 28rpx; | |
| 400 | - margin-right: 10rpx; | |
| 401 | - } | |
| 402 | - } | |
| 403 | - } | |
| 404 | - } | |
| 405 | - } | |
| 406 | -} | |
| 407 | - | |
| 408 | -.filter { | |
| 409 | - padding: 0 30rpx; | |
| 410 | - .filter-title { | |
| 411 | - text-align: center; | |
| 412 | - margin-top: 14px; | |
| 413 | - font-size: 16px; | |
| 414 | - font-weight: 700; | |
| 415 | - } | |
| 416 | - .button-group { | |
| 417 | - display: flex; | |
| 418 | - margin-top: 40rpx; | |
| 419 | - justify-content: space-between; | |
| 420 | - view { | |
| 421 | - width: 330rpx; | |
| 422 | - } | |
| 423 | - } | |
| 424 | -} | |
| 425 | -</style> |
feedback-subpackage/feedback/config/data.js
0 → 100644
| 1 | +const rules = { | |
| 2 | + 'feedbackInfo.title': { | |
| 3 | + type: 'string', | |
| 4 | + required: true, | |
| 5 | + message: '请输入主题', | |
| 6 | + trigger: ['blur', 'change'] | |
| 7 | + }, | |
| 8 | + 'feedbackInfo.name': { | |
| 9 | + type: 'string', | |
| 10 | + required: true, | |
| 11 | + message: '请输入姓名', | |
| 12 | + trigger: ['blur', 'change'] | |
| 13 | + }, | |
| 14 | + 'feedbackInfo.message': { | |
| 15 | + type: 'string', | |
| 16 | + required: true, | |
| 17 | + message: '请输入意见反馈', | |
| 18 | + trigger: ['blur', 'change'] | |
| 19 | + } | |
| 20 | +} | |
| 21 | +export { | |
| 22 | + rules | |
| 23 | +} | |
| \ No newline at end of file | ... | ... |
feedback-subpackage/feedback/feedback.vue
renamed from
feedBackSubPage/feedback/feedback.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="feedback-page"> |
| 3 | - <view style="overflow-y: scroll;overflow: hidden;height: 1500rpx;"> | |
| 3 | + <view class="feedback-container"> | |
| 4 | 4 | <!-- 公共组件-每个页面必须引入 --> |
| 5 | 5 | <public-module></public-module> |
| 6 | 6 | <view class="form-page"> |
| 7 | 7 | <u--form labelPosition="left" :model="feedbackData" :rules="rules" ref="myfeedBackFormRef"> |
| 8 | - <u-form-item required label="主题" prop="feedbackInfo.title" borderBottom ref="item1"> | |
| 8 | + <u-form-item required label="主题" prop="feedbackInfo.title" borderBottom> | |
| 9 | 9 | <u--input placeholder="请输入主题" v-model="feedbackData.feedbackInfo.title" border="none"> |
| 10 | 10 | </u--input> |
| 11 | 11 | </u-form-item> |
| 12 | - <u-form-item required label="姓名" prop="feedbackInfo.name" borderBottom ref="item1"> | |
| 12 | + <u-form-item required label="姓名" prop="feedbackInfo.name" borderBottom> | |
| 13 | 13 | <u--input placeholder="请输入姓名" v-model="feedbackData.feedbackInfo.name" border="none"></u--input> |
| 14 | 14 | </u-form-item> |
| 15 | + <u-form-item required label="反馈" prop="feedbackInfo.message" borderBottom> | |
| 16 | + <u--textarea placeholder="请输入反馈信息" v-model="feedbackData.feedbackInfo.message" count> | |
| 17 | + </u--textarea> | |
| 18 | + </u-form-item> | |
| 19 | + <view class="feed-back-text upload-text">上传图片(最多6张)</view> | |
| 15 | 20 | <view class="info"> |
| 16 | 21 | <view class="info-contain"> |
| 17 | - <u-form-item required label="反馈" prop="feedbackInfo.message" borderBottom ref="item1"> | |
| 18 | - <u--textarea placeholder="请输入反馈信息" v-model="feedbackData.feedbackInfo.message" count> | |
| 19 | - </u--textarea> | |
| 20 | - </u-form-item> | |
| 21 | - </view> | |
| 22 | - </view> | |
| 23 | - <view class="feed-back-text" style="margin: 15px 0px 0px -16rpx;">上传图片(最多6张)</view> | |
| 24 | - <view class="info" style="margin-top: 15rpx;background: rgba(1, 1, 1, 0);"> | |
| 25 | - <view class="info-contain"> | |
| 26 | - <u-form-item label="图片" prop="feedbackInfo.images" borderBottom ref="item1"> | |
| 22 | + <u-form-item label="图片" prop="feedbackInfo.images" borderBottom> | |
| 27 | 23 | <u-upload :capture="capture" :fileList="fileList1" @afterRead="afterRead" |
| 28 | 24 | @delete="deletePic" name="1" multiple :maxCount="6"></u-upload> |
| 29 | 25 | </u-form-item> |
| 30 | 26 | </view> |
| 31 | - <view style="width:427rpx;margin:0 auto;"> | |
| 27 | + <view class="info-button"> | |
| 28 | + <!-- #ifdef MP --> | |
| 29 | + <u-button class="buttonSty button-sty" shape="circle" type="primary" text="提交" | |
| 30 | + customStyle="margin-top: 280rpx" @click="submit"></u-button> | |
| 31 | + <!-- #endif --> | |
| 32 | + <!-- #ifdef APP-PLUS --> | |
| 32 | 33 | <u-button class="buttonSty button-sty" shape="circle" type="primary" text="提交" |
| 33 | - customStyle="margin-top: 129rpx" @click="submit"></u-button> | |
| 34 | + customStyle="margin-top: 880rpx" @click="submit"></u-button> | |
| 35 | + <!-- #endif --> | |
| 34 | 36 | </view> |
| 35 | 37 | </view> |
| 36 | 38 | </u--form> |
| ... | ... | @@ -53,6 +55,8 @@ |
| 53 | 55 | mapState |
| 54 | 56 | } from 'vuex'; |
| 55 | 57 | import api from '@/api/index.js' |
| 58 | + import { rules } from './config/data.js' | |
| 59 | + import { UPLOAD_FILE_SIZE } from '@/constant/index.js' | |
| 56 | 60 | |
| 57 | 61 | export default { |
| 58 | 62 | data() { |
| ... | ... | @@ -67,27 +71,7 @@ |
| 67 | 71 | } |
| 68 | 72 | }, |
| 69 | 73 | fileList1: [], |
| 70 | - rules: { | |
| 71 | - 'feedbackInfo.title': { | |
| 72 | - type: 'string', | |
| 73 | - required: true, | |
| 74 | - message: '请输入主题', | |
| 75 | - trigger: ['blur', 'change'] | |
| 76 | - }, | |
| 77 | - 'feedbackInfo.name': { | |
| 78 | - type: 'string', | |
| 79 | - required: true, | |
| 80 | - message: '请输入姓名', | |
| 81 | - trigger: ['blur', 'change'] | |
| 82 | - }, | |
| 83 | - 'feedbackInfo.message': { | |
| 84 | - type: 'string', | |
| 85 | - required: true, | |
| 86 | - message: '请输入意见反馈', | |
| 87 | - trigger: ['blur', 'change'] | |
| 88 | - }, | |
| 89 | - | |
| 90 | - }, | |
| 74 | + rules | |
| 91 | 75 | }; |
| 92 | 76 | }, |
| 93 | 77 | onReady() { |
| ... | ... | @@ -111,7 +95,7 @@ |
| 111 | 95 | let lists = [].concat(event.file); |
| 112 | 96 | let fileListLen = this[`fileList${event.name}`].length; |
| 113 | 97 | lists.map(item => { |
| 114 | - if (item.size > 5242880) { | |
| 98 | + if (item.size > UPLOAD_FILE_SIZE) { | |
| 115 | 99 | this[`fileList${event.name}`].push({ |
| 116 | 100 | ...item, |
| 117 | 101 | status: 'error', |
| ... | ... | @@ -127,7 +111,7 @@ |
| 127 | 111 | }); |
| 128 | 112 | for (let i = 0; i < lists.length; i++) { |
| 129 | 113 | const judgeImageSize = lists[0].size |
| 130 | - if (judgeImageSize > 5242880) { | |
| 114 | + if (judgeImageSize > UPLOAD_FILE_SIZE) { | |
| 131 | 115 | return uni.$u.toast('图片限定5M') |
| 132 | 116 | } else { |
| 133 | 117 | const result = await this.uploadFilePromise(lists[i].url); |
| ... | ... | @@ -153,7 +137,7 @@ |
| 153 | 137 | // #endif |
| 154 | 138 | if (!token) return uni.$u.toast('请登录后上传图片'); |
| 155 | 139 | return new Promise((resolve, reject) => { |
| 156 | - let a = uni.uploadFile({ | |
| 140 | + uni.uploadFile({ | |
| 157 | 141 | url: `${baseUrl.baseUrl}/yt/oss/upload`, |
| 158 | 142 | filePath: url, |
| 159 | 143 | name: 'file', |
| ... | ... | @@ -186,7 +170,7 @@ |
| 186 | 170 | .validate() |
| 187 | 171 | .then(async res => { |
| 188 | 172 | if (res) { |
| 189 | - let httpData = { | |
| 173 | + let data = { | |
| 190 | 174 | title: this.feedbackData.feedbackInfo.title, |
| 191 | 175 | name: this.feedbackData.feedbackInfo.name, |
| 192 | 176 | images: this.feedbackData.feedbackInfo.images.length == 0 ? '' : JSON |
| ... | ... | @@ -194,11 +178,8 @@ |
| 194 | 178 | this.feedbackData.feedbackInfo.images), |
| 195 | 179 | message: this.feedbackData.feedbackInfo.message |
| 196 | 180 | }; |
| 197 | - const res = await api.feedbackApi.postFeedBackApi(httpData) | |
| 198 | - uni.showToast({ | |
| 199 | - title: '意见反馈提交成功~', | |
| 200 | - icon: 'none' | |
| 201 | - }); | |
| 181 | + const res = await api.feedbackApi.postFeedBackApi(data) | |
| 182 | + uni.$u.toast('意见反馈提交成功~'); | |
| 202 | 183 | setTimeout(() => { |
| 203 | 184 | uni.navigateBack(); |
| 204 | 185 | }, 500); |
| ... | ... | @@ -213,58 +194,7 @@ |
| 213 | 194 | </script> |
| 214 | 195 | |
| 215 | 196 | <style lang="scss" scoped> |
| 216 | - .feedback-page { | |
| 217 | - min-height: 100vh; | |
| 218 | - background-color: #f8f9fa; | |
| 219 | - padding-top: 9rpx; | |
| 220 | - padding-left: 27rpx; | |
| 221 | - overflow-y: scroll; | |
| 222 | - overflow: hidden; | |
| 223 | - } | |
| 224 | - | |
| 225 | - .form-page { | |
| 226 | - width: 700rpx; | |
| 227 | - background-color: #ffffff; | |
| 228 | - border-radius: 10px; | |
| 229 | - margin-top: 20rpx; | |
| 230 | - padding-left: 15rpx; | |
| 231 | - padding: 0 20rpx; | |
| 232 | - height: 500rpx; | |
| 233 | - | |
| 234 | - .info { | |
| 235 | - width: 700rpx; | |
| 236 | - background-color: #ffffff; | |
| 237 | - border-radius: 10px; | |
| 238 | - margin-top: 100rpx; | |
| 239 | - height: 256rpx; | |
| 240 | - margin-left: -20rpx; | |
| 241 | - | |
| 242 | - .info-contain { | |
| 243 | - margin: 0rpx 27rpx; | |
| 244 | - | |
| 245 | - /deep/ .u-line { | |
| 246 | - display: none !important; | |
| 247 | - } | |
| 248 | - | |
| 249 | - /deep/ .u-form-item__body__left__content__label { | |
| 250 | - display: none !important; | |
| 251 | - } | |
| 252 | - | |
| 253 | - /deep/.u-form-item__body__right { | |
| 254 | - margin-left: -106rpx; | |
| 255 | - } | |
| 256 | - | |
| 257 | - /deep/.u-textarea--radius { | |
| 258 | - border: none !important; | |
| 259 | - } | |
| 260 | - } | |
| 261 | - } | |
| 262 | - | |
| 263 | - /deep/.u-button--primary { | |
| 264 | - background-color: #377DFF !important; | |
| 265 | - border-color: #377DFF !important; | |
| 266 | - } | |
| 267 | - } | |
| 197 | + @import "./static/feedback.scss"; | |
| 268 | 198 | |
| 269 | 199 | //#ifndef MP |
| 270 | 200 | .buttonSty { |
| ... | ... | @@ -272,4 +202,4 @@ |
| 272 | 202 | } |
| 273 | 203 | |
| 274 | 204 | //#endif |
| 275 | -</style> | |
| 205 | +</style> | |
| \ No newline at end of file | ... | ... |
| 1 | +.feedback-page { | |
| 2 | + min-height: 100vh; | |
| 3 | + background-color: #f8f9fa; | |
| 4 | + padding-top: 9rpx; | |
| 5 | + padding-left: 27rpx; | |
| 6 | + overflow-y: scroll; | |
| 7 | + overflow: hidden; | |
| 8 | + .feedback-container{ | |
| 9 | + overflow-y: scroll; | |
| 10 | + overflow: hidden; | |
| 11 | + height: 1500rpx; | |
| 12 | + } | |
| 13 | + } | |
| 14 | + | |
| 15 | + .form-page { | |
| 16 | + width: 700rpx; | |
| 17 | + background-color: #ffffff; | |
| 18 | + border-radius: 10px; | |
| 19 | + margin-top: 20rpx; | |
| 20 | + padding: 0 40rpx; | |
| 21 | + height: 860rpx; | |
| 22 | + .upload-text{ | |
| 23 | + margin: 15px 0px 0px -16rpx; | |
| 24 | + } | |
| 25 | + | |
| 26 | + .info { | |
| 27 | + width: 700rpx; | |
| 28 | + background-color: #ffffff; | |
| 29 | + border-radius: 10px; | |
| 30 | + margin-top: 100rpx; | |
| 31 | + height: 256rpx; | |
| 32 | + margin-left: -20rpx; | |
| 33 | + margin-top: 15rpx; | |
| 34 | + background: rgba(1, 1, 1, 0); | |
| 35 | + | |
| 36 | + .info-contain { | |
| 37 | + margin: 0rpx 27rpx; | |
| 38 | + | |
| 39 | + /deep/ .u-line { | |
| 40 | + display: none !important; | |
| 41 | + } | |
| 42 | + | |
| 43 | + /deep/ .u-form-item__body__left__content__label { | |
| 44 | + display: none !important; | |
| 45 | + } | |
| 46 | + | |
| 47 | + /deep/.u-form-item__body__right { | |
| 48 | + margin-left: -106rpx; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /deep/.u-textarea--radius { | |
| 52 | + border: none !important; | |
| 53 | + } | |
| 54 | + } | |
| 55 | + .info-button{ | |
| 56 | + width:427rpx; | |
| 57 | + margin:0 auto; | |
| 58 | + } | |
| 59 | + } | |
| 60 | + | |
| 61 | + /deep/.u-button--primary { | |
| 62 | + background-color: #377DFF !important; | |
| 63 | + border-color: #377DFF !important; | |
| 64 | + } | |
| 65 | + } | |
| \ No newline at end of file | ... | ... |
login-subpackage/other/code.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="code-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view class="login-body"> | |
| 6 | + <view class="login-phone"> | |
| 7 | + <view class="phone-main"> | |
| 8 | + <text class="text">手机验证码登录</text> | |
| 9 | + <view class="circleStyle"></view> | |
| 10 | + </view> | |
| 11 | + <view class="form-row"><u-input v-model="loginForm.phoneNumber" type="number" placeholder="请输入手机号码" | |
| 12 | + border="bottom"></u-input></view> | |
| 13 | + <view class="form-row"> | |
| 14 | + <u-input type="number" v-model="loginForm.code" placeholder="请输入验证码" border="bottom"> | |
| 15 | + <template slot="suffix"> | |
| 16 | + <view @click="getVerifyCode" class="verify-code">{{ codeText }}</view> | |
| 17 | + </template> | |
| 18 | + </u-input> | |
| 19 | + </view> | |
| 20 | + <button class="submit" size="default" @click="onSubmit"><text class="text">登录</text></button> | |
| 21 | + <view class="u-flex account-style"> | |
| 22 | + <view class="content" @click="openAccountFunc">账号密码登录</view> | |
| 23 | + </view> | |
| 24 | + <view class="circleStyleBottom"></view> | |
| 25 | + </view> | |
| 26 | + </view> | |
| 27 | + </view> | |
| 28 | +</template> | |
| 29 | + | |
| 30 | +<script> | |
| 31 | + var clear; | |
| 32 | + import {mapState,mapMutations,mapActions} from 'vuex'; | |
| 33 | + import {useShowToast,useNavigateTo,useReLaunch} from '@/plugins/utils.js' | |
| 34 | + import api from '@/api' | |
| 35 | + | |
| 36 | + export default { | |
| 37 | + data() { | |
| 38 | + return { | |
| 39 | + loginForm: { | |
| 40 | + phoneNumber: '', | |
| 41 | + code: '' | |
| 42 | + }, | |
| 43 | + readonly: false, | |
| 44 | + codeText: '发送验证码', | |
| 45 | + }; | |
| 46 | + }, | |
| 47 | + methods: { | |
| 48 | + ...mapMutations(['setUserInfo']), | |
| 49 | + ...mapActions(['updateBadgeTotal']), | |
| 50 | + //验证码按钮文字状态 | |
| 51 | + codeCountdownText() { | |
| 52 | + const _this = this; | |
| 53 | + this.readonly = true; | |
| 54 | + this.codeText = '60s后重新获取'; | |
| 55 | + var s = 60; | |
| 56 | + clear = setInterval(() => { | |
| 57 | + s--; | |
| 58 | + _this.codeText = s + 's后重新获取'; | |
| 59 | + if (s <= 0) { | |
| 60 | + clearInterval(clear); | |
| 61 | + _this.codeText = '发送验证码'; | |
| 62 | + _this.readonly = false; | |
| 63 | + } | |
| 64 | + }, 1000); | |
| 65 | + }, | |
| 66 | + //获取验证码 | |
| 67 | + async getVerifyCode() { | |
| 68 | + const phoneRegular = /^1\d{10}$/; | |
| 69 | + if (this.readonly) { | |
| 70 | + useShowToast('验证码已发送~') | |
| 71 | + } | |
| 72 | + if (!this.loginForm.phoneNumber) { | |
| 73 | + return useShowToast('请输入手机号~') | |
| 74 | + } | |
| 75 | + if (!phoneRegular.test(this.loginForm.phoneNumber)) { | |
| 76 | + return useShowToast('手机号格式不正确~') | |
| 77 | + } | |
| 78 | + // 获取验证码接口 | |
| 79 | + await api.loginApi.postPhoneCodeApi(this.loginForm.phoneNumber) | |
| 80 | + this.codeCountdownText(); //开始倒计时 | |
| 81 | + }, | |
| 82 | + async onSubmit() { | |
| 83 | + const phoneRegular = /^1\d{10}$/; | |
| 84 | + const verifyCodeReg = /^\d{6}$/; | |
| 85 | + const validateValue = Object.values(this.loginForm) | |
| 86 | + if (!validateValue[0]) return uni.$u.toast("请输入手机号码~"); | |
| 87 | + if (!validateValue[1]) return uni.$u.toast("请输入验证码~"); | |
| 88 | + if (!phoneRegular.test(validateValue[0])) return uni.$u.toast("手机号格式不正确~"); | |
| 89 | + if (!verifyCodeReg.test(validateValue[1])) return uni.$u.toast("验证码格式不正确~"); | |
| 90 | + const res = await api.loginApi.postPhoneLoginApi(this.loginForm) | |
| 91 | + if (res) { | |
| 92 | + // 储存登录信息 | |
| 93 | + let tokenInfo = { | |
| 94 | + refreshToken: res.refreshToken, | |
| 95 | + isToken: res.token | |
| 96 | + }; | |
| 97 | + let userInfo = { | |
| 98 | + ...tokenInfo, | |
| 99 | + token: true, //token用于判断是否登录 | |
| 100 | + isThirdLogin: false | |
| 101 | + }; | |
| 102 | + if (userInfo.token) { | |
| 103 | + this.setUserInfo(userInfo); | |
| 104 | + } | |
| 105 | + useShowToast('登录成功~').then(async (res) => { | |
| 106 | + this.saveUserInfo(); | |
| 107 | + await this.getAlarmTotalData(); | |
| 108 | + useReLaunch("/pages/index/index") | |
| 109 | + }); | |
| 110 | + } | |
| 111 | + }, | |
| 112 | + async getAlarmTotalData() { | |
| 113 | + const res = await await api.loginApi.getAlarmTotalApi() | |
| 114 | + if (!res) return | |
| 115 | + //异步实时更新告警徽标数 | |
| 116 | + this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 117 | + }, | |
| 118 | + async saveUserInfo() { | |
| 119 | + //储存个人信息 | |
| 120 | + const res = await api.loginApi.setUserInfoApi() | |
| 121 | + if (!res) return | |
| 122 | + this.setUserInfo(res); | |
| 123 | + }, | |
| 124 | + openAccountFunc() { | |
| 125 | + useNavigateTo('../public/login') | |
| 126 | + } | |
| 127 | + } | |
| 128 | + }; | |
| 129 | +</script> | |
| 130 | + | |
| 131 | +<style lang="scss" scoped> | |
| 132 | + @import './static/code.scss'; | |
| 133 | +</style> | |
| \ No newline at end of file | ... | ... |
login-subpackage/other/find-password.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="find-password-page"> | |
| 3 | + <public-module></public-module> | |
| 4 | + <view class="top u-flex"> | |
| 5 | + <view @click="showPhone" :style="{ color: phoneNumberColor }" class="item">1.验证手机号码</view> | |
| 6 | + <view :style="{ color: passwordColor }" class="item">2.设置新密码</view> | |
| 7 | + </view> | |
| 8 | + <view v-if="!nextStatus" class="login-body"> | |
| 9 | + <view class="login-phone"> | |
| 10 | + <view class="form-row"> | |
| 11 | + <u-input v-model="forgetForm.phone" type="number" placeholder="请输入手机号码" border="bottom" /> | |
| 12 | + </view> | |
| 13 | + <view class="form-row"> | |
| 14 | + <u-input type="number" v-model="forgetForm.verifyCode" placeholder="请输入验证码" border="bottom"> | |
| 15 | + <template slot="suffix"> | |
| 16 | + <view @click="getVerifyCode" class="verify-code">{{ codeText }}</view> | |
| 17 | + </template> | |
| 18 | + </u-input> | |
| 19 | + </view> | |
| 20 | + <button class="submit" size="default" @click="onNextSubmit"><text style="color:#fff">下一步</text></button> | |
| 21 | + </view> | |
| 22 | + </view> | |
| 23 | + <view v-else class="login-body"> | |
| 24 | + <view class="login-phone"> | |
| 25 | + <view class="form-row u-flex"> | |
| 26 | + <u-input v-model="forgetForm.password" :password="showPassword" placeholder="请设置6-20位新的登录密码" border="bottom"> | |
| 27 | + <template slot="suffix"> | |
| 28 | + <view @click="showPasswordMode" style="padding: 10rpx"> | |
| 29 | + <u-icon width="18" height="14" :name="passwordModeIcon"></u-icon> | |
| 30 | + </view> | |
| 31 | + </template> | |
| 32 | + </u-input> | |
| 33 | + </view> | |
| 34 | + <view class="form-row u-flex"> | |
| 35 | + <u-input v-model="forgetForm.repeatPassword" :password="showPasswordRepeat" placeholder="请再次输入新的登录密码" border="bottom"> | |
| 36 | + <template slot="suffix"> | |
| 37 | + <view @click="showPasswordModeRepeat" style="padding: 10rpx"> | |
| 38 | + <u-icon width="18" height="14" :name="passwordModeRepeatIcon"></u-icon> | |
| 39 | + </view> | |
| 40 | + </template> | |
| 41 | + </u-input> | |
| 42 | + </view> | |
| 43 | + <button class="submit" size="default" @click="onSubmit"><text style="color:#fff">确定</text></button> | |
| 44 | + </view> | |
| 45 | + </view> | |
| 46 | + </view> | |
| 47 | +</template> | |
| 48 | + | |
| 49 | +<script> | |
| 50 | + import api from '@/api/index.js' | |
| 51 | + import { loginPasswordReg } from '@/plugins/utils.js' | |
| 52 | + import { useShowToast,useShowModal,useReLaunch } from '@/plugins/utils.js' | |
| 53 | + | |
| 54 | + var clear; | |
| 55 | + export default { | |
| 56 | + data() { | |
| 57 | + return { | |
| 58 | + forgetForm:{ | |
| 59 | + phone: '', | |
| 60 | + verifyCode: '', | |
| 61 | + password: '', | |
| 62 | + repeatPassword: '', | |
| 63 | + }, | |
| 64 | + readonly: false, | |
| 65 | + codeText: '发送验证码', | |
| 66 | + nextStatus: false, | |
| 67 | + showPassword: true, | |
| 68 | + showPasswordRepeat: true | |
| 69 | + }; | |
| 70 | + }, | |
| 71 | + computed:{ | |
| 72 | + phoneNumberColor(){ | |
| 73 | + return !this.nextStatus ? '#0079fe' : '' | |
| 74 | + }, | |
| 75 | + passwordColor(){ | |
| 76 | + return !this.nextStatus ? '' : '#0079fe' | |
| 77 | + }, | |
| 78 | + passwordModeIcon(){ | |
| 79 | + return this.showPassword ? '/static/eye-hide.png' : '/static/eye.png' | |
| 80 | + }, | |
| 81 | + passwordModeRepeatIcon(){ | |
| 82 | + return this.showPasswordRepeat ? '/static/eye-hide.png' : '/static/eye.png' | |
| 83 | + } | |
| 84 | + }, | |
| 85 | + methods: { | |
| 86 | + //验证码按钮文字状态 | |
| 87 | + verifyCodeCountDown() { | |
| 88 | + const _this = this; | |
| 89 | + this.readonly = true; | |
| 90 | + this.codeText = '60s后重新获取'; | |
| 91 | + var s = 60; | |
| 92 | + clear = setInterval(() => { | |
| 93 | + s--; | |
| 94 | + _this.codeText = s + 's后重新获取'; | |
| 95 | + if (s <= 0) { | |
| 96 | + clearInterval(clear); | |
| 97 | + _this.codeText = '发送验证码'; | |
| 98 | + _this.readonly = false; | |
| 99 | + } | |
| 100 | + }, 1000); | |
| 101 | + }, | |
| 102 | + //获取验证码 | |
| 103 | + getVerifyCode() { | |
| 104 | + const phoneRegular = /^1\d{10}$/; | |
| 105 | + if (this.readonly) { | |
| 106 | + useShowToast('验证码已发送~') | |
| 107 | + } | |
| 108 | + console.log(this.forgetForm.phone); | |
| 109 | + if (!this.forgetForm.phone) { | |
| 110 | + return useShowToast('请输入手机号~') | |
| 111 | + } | |
| 112 | + if (!phoneRegular.test(this.forgetForm.phone)) { | |
| 113 | + return useShowToast('手机号格式不正确~') | |
| 114 | + } | |
| 115 | + api.loginApi.postCodeApi(this.forgetForm.phone) | |
| 116 | + .then(res => { | |
| 117 | + this.verifyCodeCountDown(); //开始倒计时 | |
| 118 | + }) | |
| 119 | + }, | |
| 120 | + onNextSubmit() { | |
| 121 | + const phoneRegular = /^1\d{10}$/; | |
| 122 | + const verifyCodeReg=/^\d{6}$/; | |
| 123 | + const validateValue = Object.values(this.forgetForm) | |
| 124 | + if(!validateValue[0]) return uni.$u.toast("请输入手机号码~"); | |
| 125 | + if(!validateValue[1]) return uni.$u.toast("请输入验证码~"); | |
| 126 | + if(!phoneRegular.test(validateValue[0])) return uni.$u.toast("手机号格式不正确~"); | |
| 127 | + if(!verifyCodeReg.test(validateValue[1])) return uni.$u.toast("验证码格式不正确~"); | |
| 128 | + this.nextStatus = true; | |
| 129 | + }, | |
| 130 | + showPhone() { | |
| 131 | + this.nextStatus = false; | |
| 132 | + }, | |
| 133 | + onSubmit() { | |
| 134 | + const validateValue = Object.values(this.forgetForm) | |
| 135 | + if(!validateValue[2]) return uni.$u.toast("请输入密码~"); | |
| 136 | + if(!validateValue[3]) return uni.$u.toast("请输入密码~"); | |
| 137 | + if(!loginPasswordReg.test(validateValue[2])) return useShowModal('密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~') | |
| 138 | + if(!loginPasswordReg.test(validateValue[3])) return useShowModal('密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~') | |
| 139 | + if (validateValue[2] !== validateValue[3]) return uni.$u.toast('两次输入密码不一致'); | |
| 140 | + let httpData = { | |
| 141 | + password: this.forgetForm.password, | |
| 142 | + phoneNumber: this.forgetForm.phone, | |
| 143 | + userId: this.forgetForm.verifyCode | |
| 144 | + }; | |
| 145 | + const res = api.loginApi.postResetCodeApi(this.forgetForm.phone, httpData) | |
| 146 | + if (res) { | |
| 147 | + useShowToast( '重置密码成功~').then(res => { | |
| 148 | + useReLaunch('/publicLoginSubPage/public/login') | |
| 149 | + }); | |
| 150 | + } | |
| 151 | + }, | |
| 152 | + showPasswordMode() { | |
| 153 | + this.showPassword = !this.showPassword; | |
| 154 | + }, | |
| 155 | + showPasswordModeRepeat() { | |
| 156 | + this.showPasswordRepeat = !this.showPasswordRepeat; | |
| 157 | + } | |
| 158 | + } | |
| 159 | + }; | |
| 160 | +</script> | |
| 161 | + | |
| 162 | +<style lang="scss" scoped> | |
| 163 | + @import './static/findPassword.scss'; | |
| 164 | +</style> | ... | ... |
login-subpackage/other/set.vue
renamed from
publicLoginSubPage/other/set.vue
| ... | ... | @@ -5,42 +5,40 @@ |
| 5 | 5 | <!-- #ifdef MP-WEIXIN --> |
| 6 | 6 | <view @click="upAvatar" class="u-flex set-main"> |
| 7 | 7 | <view class="main-image"> |
| 8 | - <image class="image" :src="avatar || '../../static/logo.png'"></image> | |
| 8 | + <image class="image" :src="uploadImage"></image> | |
| 9 | 9 | </view> |
| 10 | 10 | <view class="main-right-image"> |
| 11 | - <image class="image" src="../../static/arrow-right.png"></image> | |
| 11 | + <image class="image" src="/static/arrow-right.png"></image> | |
| 12 | 12 | </view> |
| 13 | 13 | </view> |
| 14 | 14 | <!-- #endif --> |
| 15 | 15 | <!-- #ifdef APP-PLUS --> |
| 16 | + <!-- 这里上传写两道的原因是,如果是app端,则兼容打开相机拍照上传 --> | |
| 16 | 17 | <view @click="upAppAvatar" class="u-flex set-main"> |
| 17 | 18 | <view class="main-image"> |
| 18 | - <image class="image" :src="avatar || '../../static/logo.png'"></image> | |
| 19 | + <image class="image" :src="uploadImage"></image> | |
| 19 | 20 | </view> |
| 20 | 21 | <view class="main-right-image"> |
| 21 | - <image class="image" src="../../static/arrow-right.png"></image> | |
| 22 | + <image class="image" src="/static/arrow-right.png"></image> | |
| 22 | 23 | </view> |
| 23 | 24 | </view> |
| 24 | 25 | <!-- #endif --> |
| 25 | 26 | <view class="u-m-t-20 basic-text"><text class="text">基本资料</text></view> |
| 26 | 27 | <view class="basic-main"> |
| 27 | 28 | <u--form labelPosition="left" :model="myInfoModel" ref="myForm"> |
| 28 | - <u-form-item labelWidth="80px" label="真实姓名" prop="realName" borderBottom ref="item1"> | |
| 29 | + <u-form-item labelWidth="80px" label="真实姓名" prop="realName" borderBottom> | |
| 29 | 30 | <u--input placeholder="请输入真实姓名" v-model="myInfoModel.realName" border="none"></u--input> |
| 30 | 31 | </u-form-item> |
| 31 | - <u-form-item labelWidth="80px" label="手机号码" prop="phoneNumber" borderBottom ref="item1"> | |
| 32 | + <u-form-item labelWidth="80px" label="手机号码" prop="phoneNumber" borderBottom> | |
| 32 | 33 | <u--input placeholder="请输入手机号码" v-model="myInfoModel.phoneNumber" border="none"></u--input> |
| 33 | 34 | </u-form-item> |
| 34 | - <u-form-item labelWidth="80px" label="用户账号" prop="username" borderBottom ref="item1"> | |
| 35 | + <u-form-item labelWidth="80px" label="用户账号" prop="username" borderBottom> | |
| 35 | 36 | <u--input disabled placeholder="请输入用户账号 " v-model="myInfoModel.username" border="none"></u--input> |
| 36 | 37 | </u-form-item> |
| 37 | - <u-form-item labelWidth="80px" label="邮箱地址" prop="email" borderBottom ref="item1"> | |
| 38 | + <u-form-item labelWidth="80px" label="邮箱地址" prop="email" borderBottom> | |
| 38 | 39 | <u--input placeholder="请输入邮箱地址" v-model="myInfoModel.email" border="none"></u--input> |
| 39 | 40 | </u-form-item> |
| 40 | - <u-form-item @click=" | |
| 41 | - showDate = true; | |
| 42 | - hideKeyboard(); | |
| 43 | - " labelWidth="80px" label="有效期" prop="accountExpireTime" ref="item1"> | |
| 41 | + <u-form-item @click="hideKeyboard" labelWidth="80px" label="有效期" prop="accountExpireTime"> | |
| 44 | 42 | <u--input v-model="myInfoModel.accountExpireTime" placeholder="请选择有效期" border="none"></u--input> |
| 45 | 43 | <u-datetime-picker :formatter="formatter" :show="showDate" :value="datetime" mode="dateTime" |
| 46 | 44 | closeOnClickOverlay @confirm="dateConfirm" @cancel="dateClose" @close="dateClose"> |
| ... | ... | @@ -61,7 +59,7 @@ |
| 61 | 59 | class="un-bind-text">确认</text></button> |
| 62 | 60 | </view> |
| 63 | 61 | </view> |
| 64 | - <!-- #ifdef MP --> | |
| 62 | + <!-- #ifdef MP-WEIXIN --> | |
| 65 | 63 | <view class="u-m-t-40"><text style="visibility: hidden;">#</text></view> |
| 66 | 64 | <!-- #endif --> |
| 67 | 65 | <!-- 解绑账号 --> |
| ... | ... | @@ -85,11 +83,10 @@ |
| 85 | 83 | mapMutations |
| 86 | 84 | } from 'vuex'; |
| 87 | 85 | import baseUrl from '@/config/baseUrl.js'; |
| 88 | - import { | |
| 89 | - mapState | |
| 90 | - } from 'vuex'; | |
| 86 | + import {mapState} from 'vuex'; | |
| 91 | 87 | import api from '@/api/index.js' |
| 92 | 88 | import permission from '@/js_sdk/wa-permission/permission.js' |
| 89 | + import {useShowModal,useUploadFile,useChooseImage,useFileValidate} from '@/plugins/utils.js' | |
| 93 | 90 | |
| 94 | 91 | export default { |
| 95 | 92 | data() { |
| ... | ... | @@ -114,7 +111,6 @@ |
| 114 | 111 | email: '', |
| 115 | 112 | accountExpireTime: '' |
| 116 | 113 | }, |
| 117 | - | |
| 118 | 114 | rules: { |
| 119 | 115 | phoneNumber: [{ |
| 120 | 116 | required: true, |
| ... | ... | @@ -153,14 +149,10 @@ |
| 153 | 149 | }, |
| 154 | 150 | onLoad(e) { |
| 155 | 151 | if (e.data !== null) { |
| 156 | - let params = JSON.parse(e.data); | |
| 152 | + let params = JSON.parse(decodeURIComponent(e.data)); | |
| 153 | + for (let i in this.myInfoModel) Reflect.set(this.myInfoModel, i, params.data[i]) | |
| 157 | 154 | this.info = params; |
| 158 | - this.myInfoModel.realName = params.data.realName; | |
| 159 | - this.myInfoModel.phoneNumber = params.data.phoneNumber; | |
| 160 | - this.myInfoModel.username = params.data.username; | |
| 161 | - this.myInfoModel.email = params.data.email; | |
| 162 | - this.myInfoModel.accountExpireTime = params.data.accountExpireTime; | |
| 163 | - this.avatar = params.data.avatar == undefined ? '../../static/logo.png' : params.data.avatar; | |
| 155 | + this.avatar = params.data.avatar == undefined ? '/static/logo.png' : params.data.avatar; | |
| 164 | 156 | this.id = params.data.userId; |
| 165 | 157 | } |
| 166 | 158 | }, |
| ... | ... | @@ -168,24 +160,22 @@ |
| 168 | 160 | let getOpenId = getApp().globalData.openId; |
| 169 | 161 | if (getOpenId) { |
| 170 | 162 | this.openIds = getOpenId; |
| 171 | - console.log('OPenid', this.openIds); | |
| 172 | 163 | } |
| 173 | 164 | }, |
| 174 | 165 | computed: { |
| 175 | - ...mapState(['userInfo']) | |
| 166 | + uploadImage() { | |
| 167 | + return this.avatar || '/static/logo.png' | |
| 168 | + } | |
| 176 | 169 | }, |
| 177 | 170 | methods: { |
| 171 | + ...mapState(['userInfo']), | |
| 172 | + ...mapMutations(['setUserInfo', 'emptyUserInfo']), | |
| 178 | 173 | modify() { |
| 179 | - uni.showModal({ | |
| 180 | - title: '需要下列权限才可以正常使用', | |
| 181 | - content: this.modify_content, | |
| 182 | - confirmText: '前往开启', | |
| 183 | - success: function(res) { | |
| 184 | - if (res.confirm) { | |
| 185 | - permission.gotoAppPermissionSetting(); //动态修改权限 | |
| 186 | - } | |
| 174 | + useShowModal(this.modify_content, '需要下列权限才可以正常使用', '前往开启').then((res) => { | |
| 175 | + if (res.confirm) { | |
| 176 | + permission.gotoAppPermissionSetting(); //动态修改权限 | |
| 187 | 177 | } |
| 188 | - }); | |
| 178 | + }) | |
| 189 | 179 | }, |
| 190 | 180 | async requestAndroidPermission(permissionID, e) { |
| 191 | 181 | let resp = await permission.requestAndroidPermission(permissionID, e); |
| ... | ... | @@ -193,14 +183,14 @@ |
| 193 | 183 | this.modify(); |
| 194 | 184 | } else if (resp == 1) { |
| 195 | 185 | if (e == 1) { |
| 196 | - this.chooseImage1() | |
| 186 | + this.nativeCameraChooseFile() | |
| 197 | 187 | } else { |
| 198 | - this.chooseImage2() | |
| 188 | + this.chooseLocalAlbum() | |
| 199 | 189 | } |
| 200 | 190 | } |
| 201 | 191 | }, |
| 202 | - ...mapMutations(['setUserInfo', 'emptyUserInfo']), | |
| 203 | - chooseImage1() { | |
| 192 | + //使用相机上传 | |
| 193 | + nativeCameraChooseFile() { | |
| 204 | 194 | let token; |
| 205 | 195 | token = this.userInfo.isToken || uni.getStorageSync('userInfo').isToken || undefined; |
| 206 | 196 | // #ifdef H5 |
| ... | ... | @@ -213,32 +203,26 @@ |
| 213 | 203 | cmr.captureImage( |
| 214 | 204 | (path) => { |
| 215 | 205 | this.showSelectType = false |
| 216 | - uni.uploadFile({ | |
| 217 | - url: `${baseUrl.baseUrl}/yt/oss/upload`, | |
| 218 | - filePath: path, | |
| 219 | - name: 'file', | |
| 220 | - header: { | |
| 206 | + useUploadFile(`${baseUrl.baseUrl}/yt/oss/upload`, path, 'file', {}, { | |
| 221 | 207 | 'content-type': 'multipart/form-data', |
| 222 | 208 | Authorization: 'Bearer ' + token |
| 223 | - }, | |
| 224 | - formData: {}, | |
| 225 | - success: res => { | |
| 209 | + }) | |
| 210 | + .then(res => { | |
| 226 | 211 | let objImage = JSON.parse(res.data); |
| 227 | 212 | this.avatar = objImage.fileStaticUri; |
| 228 | 213 | uni.$u.toast('头像上传成功'); |
| 229 | - } | |
| 230 | - }); | |
| 214 | + }) | |
| 231 | 215 | }, |
| 232 | 216 | function(error) { |
| 233 | - console.log('Capture image failed: ' + error.message); | |
| 217 | + uni.$u.toast('Capture image failed: ' + error.message); | |
| 234 | 218 | }, { |
| 235 | 219 | resolution: res, |
| 236 | 220 | format: fmt |
| 237 | 221 | } |
| 238 | 222 | ); |
| 239 | 223 | }, |
| 240 | - //选择相册 | |
| 241 | - chooseImage2() { | |
| 224 | + //选择相册上传 | |
| 225 | + chooseLocalAlbum() { | |
| 242 | 226 | let token; |
| 243 | 227 | token = this.userInfo.isToken || uni.getStorageSync('userInfo').isToken || undefined; |
| 244 | 228 | // #ifdef H5 |
| ... | ... | @@ -247,26 +231,19 @@ |
| 247 | 231 | if (!token) return uni.$u.toast('请登录后上传图片'); |
| 248 | 232 | plus.gallery.pick( |
| 249 | 233 | (path) => { |
| 250 | - console.log(path) | |
| 251 | 234 | this.showSelectType = false |
| 252 | - uni.uploadFile({ | |
| 253 | - url: `${baseUrl.baseUrl}/yt/oss/upload`, | |
| 254 | - filePath: path, | |
| 255 | - name: 'file', | |
| 256 | - header: { | |
| 235 | + useUploadFile(`${baseUrl.baseUrl}/yt/oss/upload`, path, 'file', {}, { | |
| 257 | 236 | 'content-type': 'multipart/form-data', |
| 258 | 237 | Authorization: 'Bearer ' + token |
| 259 | - }, | |
| 260 | - formData: {}, | |
| 261 | - success: res => { | |
| 238 | + }) | |
| 239 | + .then(res => { | |
| 262 | 240 | let objImage = JSON.parse(res.data); |
| 263 | 241 | this.avatar = objImage.fileStaticUri; |
| 264 | 242 | uni.$u.toast('头像上传成功'); |
| 265 | - } | |
| 266 | - }); | |
| 243 | + }) | |
| 267 | 244 | }, |
| 268 | 245 | function(e) { |
| 269 | - console.log('取消选择图片'); | |
| 246 | + uni.$u.toast('您取消选择图片'); | |
| 270 | 247 | }, { |
| 271 | 248 | filter: 'image' |
| 272 | 249 | } |
| ... | ... | @@ -281,9 +258,7 @@ |
| 281 | 258 | }; |
| 282 | 259 | api.loginApi.deleteBindApi(httpData).then(res => { |
| 283 | 260 | if (res) { |
| 284 | - uni.showToast({ | |
| 285 | - title: '解绑成功' | |
| 286 | - }); | |
| 261 | + uni.$u.toast('解绑成功'); | |
| 287 | 262 | this.showBind = false; |
| 288 | 263 | this.isJudgeBindBtn = false; |
| 289 | 264 | uni.reLaunch({ |
| ... | ... | @@ -291,9 +266,7 @@ |
| 291 | 266 | }); |
| 292 | 267 | this.emptyUserInfo(); |
| 293 | 268 | } else { |
| 294 | - uni.showToast({ | |
| 295 | - title: '解绑失败' | |
| 296 | - }); | |
| 269 | + uni.$u.toast('解绑失败'); | |
| 297 | 270 | this.showBind = false; |
| 298 | 271 | } |
| 299 | 272 | }); |
| ... | ... | @@ -334,52 +307,22 @@ |
| 334 | 307 | token = window.sessionStorage.getItem('userInfo').isToken; |
| 335 | 308 | // #endif |
| 336 | 309 | if (!token) return uni.$u.toast('请登录后上传图片'); |
| 337 | - uni.chooseImage({ | |
| 310 | + useChooseImage({ | |
| 338 | 311 | count: 1, |
| 339 | 312 | sizeType: ['compressed'], |
| 340 | - sourceType: ['camera', 'album'], | |
| 341 | - success: res => { | |
| 342 | - const tempFilePaths = res.tempFilePaths; | |
| 343 | - //限制上传的图片大小不超过5M | |
| 344 | - let resSize = res.tempFiles[0].size; | |
| 345 | - if (resSize > 5242880) { | |
| 346 | - uni.showToast({ | |
| 347 | - title: '上传的图片大小不能超过5M', | |
| 348 | - icon: 'none', | |
| 349 | - duration: 2000, | |
| 350 | - mask: true | |
| 351 | - }); | |
| 352 | - return; | |
| 353 | - } | |
| 354 | - //获取图片扩展名 | |
| 355 | - const fileTxt = res.tempFilePaths[0].split('.').pop(); | |
| 356 | - const judgeType = fileTxt == 'jpg' || fileTxt == 'jpeg' || fileTxt == 'png'; | |
| 357 | - if (!judgeType) { | |
| 358 | - uni.showToast({ | |
| 359 | - title: '请上传指定图片类型(jpg、jpeg、png)', | |
| 360 | - icon: 'none', | |
| 361 | - duration: 2000, | |
| 362 | - mask: true | |
| 363 | - }); | |
| 364 | - return; | |
| 365 | - } | |
| 366 | - uni.uploadFile({ | |
| 367 | - url: `${baseUrl.baseUrl}/yt/oss/upload`, | |
| 368 | - filePath: tempFilePaths[0], | |
| 369 | - name: 'file', | |
| 370 | - header: { | |
| 371 | - 'content-type': 'multipart/form-data', | |
| 372 | - Authorization: 'Bearer ' + token | |
| 373 | - }, | |
| 374 | - formData: {}, | |
| 375 | - success: res => { | |
| 376 | - let objImage = JSON.parse(res.data); | |
| 377 | - this.avatar = objImage.fileStaticUri; | |
| 378 | - uni.$u.toast('头像上传成功'); | |
| 379 | - } | |
| 380 | - }); | |
| 381 | - }, | |
| 382 | - }); | |
| 313 | + sourceType: ['camera', 'album'] | |
| 314 | + }).then((res) => { | |
| 315 | + useFileValidate(res[0], 5242880) | |
| 316 | + useUploadFile(`${baseUrl.baseUrl}/yt/oss/upload`, res[0].path, 'file', {}, { | |
| 317 | + 'content-type': 'multipart/form-data', | |
| 318 | + Authorization: 'Bearer ' + token | |
| 319 | + }) | |
| 320 | + .then(res => { | |
| 321 | + let objImage = JSON.parse(res.data); | |
| 322 | + this.avatar = objImage.fileStaticUri; | |
| 323 | + uni.$u.toast('头像上传成功'); | |
| 324 | + }) | |
| 325 | + }) | |
| 383 | 326 | }, |
| 384 | 327 | onSubmitFunc() { |
| 385 | 328 | let httpData = { |
| ... | ... | @@ -395,15 +338,10 @@ |
| 395 | 338 | const resp = await api.loginApi.postPersonalInfoApi(httpData) |
| 396 | 339 | if (res) { |
| 397 | 340 | this.setUserInfo(resp); |
| 398 | - uni.showToast({ | |
| 399 | - title: '更新个人资料成功~', | |
| 400 | - icon: 'none' | |
| 341 | + uni.navigateBack({ | |
| 342 | + delta: 1 | |
| 401 | 343 | }); |
| 402 | - setTimeout(() => { | |
| 403 | - uni.navigateBack({ | |
| 404 | - delta: 1 | |
| 405 | - }); | |
| 406 | - }, 500); | |
| 344 | + uni.$u.toast('更新个人资料成功~'); | |
| 407 | 345 | } |
| 408 | 346 | }) |
| 409 | 347 | .catch(errors => { |
| ... | ... | @@ -417,7 +355,6 @@ |
| 417 | 355 | this.showDate = false; |
| 418 | 356 | this.myInfoModel.userInfo.accountExpireTime = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss'); |
| 419 | 357 | }, |
| 420 | - //格式化日期 | |
| 421 | 358 | formatter(type, value) { |
| 422 | 359 | if (type === 'year') { |
| 423 | 360 | return `${value}年`; |
| ... | ... | @@ -438,6 +375,7 @@ |
| 438 | 375 | }, |
| 439 | 376 | //隐藏输入框 |
| 440 | 377 | hideKeyboard() { |
| 378 | + this.showDate = true; | |
| 441 | 379 | uni.hideKeyboard(); |
| 442 | 380 | } |
| 443 | 381 | } |
| ... | ... | @@ -465,4 +403,4 @@ |
| 465 | 403 | width: 663rpx !important; |
| 466 | 404 | } |
| 467 | 405 | } |
| 468 | -</style> | |
| 406 | +</style> | |
| \ No newline at end of file | ... | ... |
login-subpackage/other/static/code.scss
renamed from
publicLoginSubPage/other/static/code.scss
| 1 | -.code-page { | |
| 2 | - min-height: 100vh; | |
| 3 | - background-color: #fff; | |
| 4 | - width: 750rpx; | |
| 5 | - background: url(/static/login.png) no-repeat; | |
| 6 | - background-size: 750rpx 1400rpx; | |
| 7 | -} | |
| 8 | -.f__login { | |
| 9 | - padding: 48rpx 32rpx; | |
| 10 | - border-radius: 18rpx 18rpx 0 0; | |
| 11 | - z-index: 99; | |
| 12 | - position: relative; | |
| 13 | -} | |
| 14 | - | |
| 15 | -.loginPhone { | |
| 16 | - .phone-main { | |
| 17 | - .text { | |
| 18 | - font-size: 22px; | |
| 19 | - color: #3a4759; | |
| 20 | - position: relative; | |
| 21 | - z-index: 9999; | |
| 22 | - font-family: PingFangSC-Semibold, PingFang SC; | |
| 23 | - font-weight: 600; | |
| 24 | - } | |
| 25 | - } | |
| 26 | - .form-row { | |
| 27 | - margin-top: 30rpx; | |
| 28 | - .getvcode { | |
| 29 | - font-family: PingFangSC-Regular, PingFang SC; | |
| 30 | - font-weight: 400; | |
| 31 | - font-size: 14px; | |
| 32 | - color: #6299ff; | |
| 33 | - } | |
| 34 | - } | |
| 35 | - | |
| 36 | - .submit { | |
| 37 | - margin-top: 60rpx; | |
| 38 | - width: 100%; | |
| 39 | - position: relative; | |
| 40 | - background: linear-gradient(90deg, #5dc2fc 0%, #377dff 100%); | |
| 41 | - border-radius: 46px; | |
| 42 | - .text { | |
| 43 | - color: #ffffff; | |
| 44 | - } | |
| 45 | - } | |
| 46 | - .account-style { | |
| 47 | - flex-direction: row; | |
| 48 | - margin-top: 48rpx; | |
| 49 | - justify-content: space-between; | |
| 50 | - .content { | |
| 51 | - color: #999999; | |
| 52 | - font-size: 13px; | |
| 53 | - } | |
| 54 | - } | |
| 1 | +.code-page { | |
| 2 | + min-height: 100vh; | |
| 3 | + background-color: #fff; | |
| 4 | + width: 750rpx; | |
| 5 | + background: url(/static/login.png) no-repeat; | |
| 6 | + background-size: 750rpx 1400rpx; | |
| 7 | +} | |
| 8 | +.login-body { | |
| 9 | + padding: 48rpx 32rpx; | |
| 10 | + border-radius: 18rpx 18rpx 0 0; | |
| 11 | + z-index: 99; | |
| 12 | + position: relative; | |
| 13 | +} | |
| 14 | + | |
| 15 | +.login-phone { | |
| 16 | + .phone-main { | |
| 17 | + margin-top: 240rpx; | |
| 18 | + .text { | |
| 19 | + font-size: 22px; | |
| 20 | + color: #3a4759; | |
| 21 | + position: relative; | |
| 22 | + z-index: 9999; | |
| 23 | + font-family: PingFangSC-Semibold, PingFang SC; | |
| 24 | + font-weight: 600; | |
| 25 | + } | |
| 26 | + } | |
| 27 | + .form-row { | |
| 28 | + margin-top: 30rpx; | |
| 29 | + .verify-code { | |
| 30 | + font-family: PingFangSC-Regular, PingFang SC; | |
| 31 | + font-weight: 400; | |
| 32 | + font-size: 14px; | |
| 33 | + color: #6299ff; | |
| 34 | + } | |
| 35 | + } | |
| 36 | + | |
| 37 | + .submit { | |
| 38 | + margin-top: 60rpx; | |
| 39 | + width: 100%; | |
| 40 | + position: relative; | |
| 41 | + background: linear-gradient(90deg, #5dc2fc 0%, #377dff 100%); | |
| 42 | + border-radius: 46px; | |
| 43 | + .text { | |
| 44 | + color: #ffffff; | |
| 45 | + } | |
| 46 | + } | |
| 47 | + .account-style { | |
| 48 | + flex-direction: row; | |
| 49 | + margin-top: 48rpx; | |
| 50 | + justify-content: space-between; | |
| 51 | + .content { | |
| 52 | + color: #999999; | |
| 53 | + font-size: 13px; | |
| 54 | + } | |
| 55 | + } | |
| 55 | 56 | } | ... | ... |
login-subpackage/other/static/findPassword.scss
renamed from
publicLoginSubPage/other/static/findPassword.scss
| 1 | -.find-password-page { | |
| 2 | - min-height: 100vh; | |
| 3 | - background-color: #fff; | |
| 4 | -} | |
| 5 | -.top { | |
| 6 | - width: 750rpx; | |
| 7 | - height: 100rpx; | |
| 8 | - border: 0.1px solid #f7f9ff; | |
| 9 | - justify-content: space-between; | |
| 10 | - flex-direction: row; | |
| 11 | - align-items: center; | |
| 12 | - | |
| 13 | - .item { | |
| 14 | - width: 375rpx; | |
| 15 | - height: 100rpx; | |
| 16 | - border: 0.1px solid #f7f9ff; | |
| 17 | - text-align: center; | |
| 18 | - line-height: 90rpx; | |
| 19 | - } | |
| 20 | -} | |
| 21 | - | |
| 22 | -.f__login { | |
| 23 | - padding: 0 30rpx; | |
| 24 | - .loginPhone { | |
| 25 | - .form-row { | |
| 26 | - margin-top: 30rpx; | |
| 27 | - .getvcode { | |
| 28 | - font-family: PingFangSC-Regular, PingFang SC; | |
| 29 | - font-weight: 400; | |
| 30 | - font-size: 14px; | |
| 31 | - color: #6299ff; | |
| 32 | - } | |
| 33 | - } | |
| 34 | - | |
| 35 | - .submit { | |
| 36 | - margin-top: 60rpx; | |
| 37 | - width: 100%; | |
| 38 | - background: #377dff; | |
| 39 | - border-radius: 48px; | |
| 40 | - } | |
| 41 | - } | |
| 1 | +.find-password-page { | |
| 2 | + min-height: 100vh; | |
| 3 | + background-color: #fff; | |
| 4 | +} | |
| 5 | +.top { | |
| 6 | + width: 750rpx; | |
| 7 | + height: 100rpx; | |
| 8 | + border: 0.1px solid #f7f9ff; | |
| 9 | + justify-content: space-between; | |
| 10 | + flex-direction: row; | |
| 11 | + align-items: center; | |
| 12 | + | |
| 13 | + .item { | |
| 14 | + width: 375rpx; | |
| 15 | + height: 100rpx; | |
| 16 | + border: 0.1px solid #f7f9ff; | |
| 17 | + text-align: center; | |
| 18 | + line-height: 90rpx; | |
| 19 | + } | |
| 20 | +} | |
| 21 | + | |
| 22 | +.login-body { | |
| 23 | + margin-top: 40rpx; | |
| 24 | + padding: 0 30rpx; | |
| 25 | + .login-phone { | |
| 26 | + .form-row { | |
| 27 | + margin-top: 30rpx; | |
| 28 | + .verify-code { | |
| 29 | + font-family: PingFangSC-Regular, PingFang SC; | |
| 30 | + font-weight: 400; | |
| 31 | + font-size: 14px; | |
| 32 | + color: #6299ff; | |
| 33 | + } | |
| 34 | + } | |
| 35 | + | |
| 36 | + .submit { | |
| 37 | + margin-top: 60rpx; | |
| 38 | + width: 100%; | |
| 39 | + background: #377dff; | |
| 40 | + border-radius: 48px; | |
| 41 | + } | |
| 42 | + } | |
| 42 | 43 | } | ... | ... |
login-subpackage/other/static/set.scss
renamed from
publicLoginSubPage/other/static/set.scss
login-subpackage/public/login.vue
renamed from
publicLoginSubPage/public/login.vue
| 1 | -<template> | |
| 2 | - <view class="login-page" :style="{ | |
| 3 | - backgroundImage: | |
| 4 | - 'url(' + | |
| 5 | - (mpOwnConfig.bg !== undefined ? mpOwnConfig.bg : `${defaultLogo}`) + | |
| 6 | - ')', | |
| 7 | - }"> | |
| 8 | - <!-- 公共组件-每个页面必须引入 --> | |
| 9 | - <public-module></public-module> | |
| 10 | - <view class="u-flex login-main"> | |
| 11 | - <view class="content"> | |
| 12 | - <view class="hello login-text-muted">您好,</view> | |
| 13 | - <view style="width: 587rpx;" class="text-clip hello-welcome login-text-muted">欢迎来到{{ | |
| 14 | - mpOwnConfig.name !== undefined ? mpOwnConfig.name : "ThingsKit" | |
| 15 | - }}!</view> | |
| 16 | - </view> | |
| 17 | - </view> | |
| 18 | - | |
| 19 | - <view class="f__login"> | |
| 20 | - <view class="loginPhone"> | |
| 21 | - <view class="form-row u-flex"> | |
| 22 | - <u-input :adjust-position="false" v-model="loginForm.username" type="text" placeholder="请输入登录账号" | |
| 23 | - border="bottom" /> | |
| 24 | - </view> | |
| 25 | - <view class="form-row u-flex"> | |
| 26 | - <u-input :adjust-position="false" v-model="loginForm.password" :password="showPassword" | |
| 27 | - placeholder="请输入登录密码" border="bottom"> | |
| 28 | - <template slot="suffix"> | |
| 29 | - <view @click="showPasswordMode" style="padding: 10rpx"> | |
| 30 | - <u-icon width="18" height="14" :name=" | |
| 31 | - showPassword ? '/static/eye-hide.png' : '/static/eye.png' | |
| 32 | - "></u-icon> | |
| 33 | - </view> | |
| 34 | - </template> | |
| 35 | - </u-input> | |
| 36 | - </view> | |
| 37 | - <button class="submit" size="default" @click="onSubmitFunc"> | |
| 38 | - <text class="text">登录</text> | |
| 39 | - </button> | |
| 40 | - <view class="u-flex row-item"> | |
| 41 | - <view class="row-phone login-text-gray" @click="openCodeFunc">手机验证码登录</view> | |
| 42 | - <view class="row-reset login-text-gray" @click="findPassrordFunc">忘记密码</view> | |
| 43 | - </view> | |
| 44 | - <view class="u-flex link-login"> | |
| 45 | - <!-- #ifdef MP-WEIXIN --> | |
| 46 | - <view class="link-text login-text-gray">第三方账号登录</view> | |
| 47 | - <view style="height: 20rpx"></view> | |
| 48 | - <button class="link-image" @tap="handleWenxinAuthorization"> | |
| 49 | - <image class="image" src="../../static/weixin.png" mode="aspectFill"></image> | |
| 50 | - </button> | |
| 51 | - <!-- #endif --> | |
| 52 | - <!-- #ifdef APP-PLUS --> | |
| 53 | - <!-- <view class="link-text login-text-gray">第三方账号登录</view> | |
| 54 | - <view style="height: 20rpx"></view> | |
| 55 | - <button class="link-image" @click="handleAppPlusAuthorization"> | |
| 56 | - <image class="image" src="../../static/weixin.png" mode="aspectFill"></image> | |
| 57 | - </button> --> | |
| 58 | - <!-- #endif --> | |
| 59 | - </view> | |
| 60 | - </view> | |
| 61 | - </view> | |
| 62 | - </view> | |
| 63 | -</template> | |
| 64 | - | |
| 65 | -<script> | |
| 66 | - import { | |
| 67 | - mapMutations, | |
| 68 | - mapActions, | |
| 69 | - mapState | |
| 70 | - } from "vuex"; | |
| 71 | - import api from '@/api' | |
| 72 | - import { loginPasswordReg } from '@/plugins/utils.js' | |
| 73 | - | |
| 74 | - export default { | |
| 75 | - data() { | |
| 76 | - return { | |
| 77 | - loginForm: { | |
| 78 | - username: "", | |
| 79 | - password: "", | |
| 80 | - }, | |
| 81 | - showPassword: true, | |
| 82 | - code: "", | |
| 83 | - openid: "", | |
| 84 | - mpOwnConfig: {}, | |
| 85 | - defaultLogo: "/static/login.png", | |
| 86 | - }; | |
| 87 | - }, | |
| 88 | - onLoad() { | |
| 89 | - //#ifdef MP-WEIXIN | |
| 90 | - wx.login({ | |
| 91 | - success: (res) => { | |
| 92 | - if (res.code) { | |
| 93 | - this.code = res.code; | |
| 94 | - //这里获取openid | |
| 95 | - } else { | |
| 96 | - return; | |
| 97 | - } | |
| 98 | - }, | |
| 99 | - }); | |
| 100 | - //#endif | |
| 101 | - uni.setStorageSync('getConfiguration', { | |
| 102 | - isConfiguration: false | |
| 103 | - }); | |
| 104 | - }, | |
| 105 | - computed: { | |
| 106 | - ...mapState(["plateInfo"]), | |
| 107 | - }, | |
| 108 | - onShow() { | |
| 109 | - uni.setStorageSync('getConfiguration', { | |
| 110 | - isConfiguration: false | |
| 111 | - }); | |
| 112 | - this.getPlateForm(); | |
| 113 | - }, | |
| 114 | - methods: { | |
| 115 | - //获取平台定制信息 | |
| 116 | - async getPlateForm() { | |
| 117 | - const res = await api.loginApi.getPlateCustomApi() | |
| 118 | - if (res) { | |
| 119 | - this.mpOwnConfig = { | |
| 120 | - bg: res.background, | |
| 121 | - logo: res.logo, | |
| 122 | - name: res.name, | |
| 123 | - }; | |
| 124 | - } | |
| 125 | - }, | |
| 126 | - ...mapMutations(["setUserInfo", "setPlateInfo"]), | |
| 127 | - ...mapActions(["updateBadgeTotal"]), | |
| 128 | - //微信授权登录 | |
| 129 | - //#ifdef MP-WEIXIN | |
| 130 | - handleWenxinAuthorization() { | |
| 131 | - wx.getUserProfile({ | |
| 132 | - desc: "微信第三方授权", | |
| 133 | - success: async (reswenxin) => { | |
| 134 | - if ( | |
| 135 | - reswenxin.errMsg === "getUserProfile:ok" && | |
| 136 | - reswenxin.encryptedData | |
| 137 | - ) { | |
| 138 | - //获取用户信息 | |
| 139 | - let obj = { | |
| 140 | - avatarUrl: reswenxin.userInfo.avatarUrl, | |
| 141 | - thirdUserId: this.openid, | |
| 142 | - }; | |
| 143 | - const res = await api.loginApi.getThirdLoginApi(this.code) | |
| 144 | - if (res.token == "" || (res.token == null && res.thirdUserId)) { | |
| 145 | - //需要绑定 | |
| 146 | - let userInfo = { | |
| 147 | - isThirdLogin: true, //用于判断是否是第三方登录并且需要绑定账号 | |
| 148 | - avatar: obj.avatarUrl, | |
| 149 | - thirdUserId: res.thirdUserId, | |
| 150 | - }; | |
| 151 | - this.setUserInfo(userInfo); | |
| 152 | - //设置全局变量openId | |
| 153 | - getApp().globalData.openId = res.thirdUserId; | |
| 154 | - uni.reLaunch({ | |
| 155 | - url: "../../pages/personal/personal", | |
| 156 | - }); | |
| 157 | - } else { | |
| 158 | - // 不需要绑定,直接第三方登录使用 | |
| 159 | - let resObj = { | |
| 160 | - refreshToken: res.refreshToken, | |
| 161 | - isToken: res.token, | |
| 162 | - }; | |
| 163 | - let userInfo = { | |
| 164 | - ...resObj, | |
| 165 | - token: true, //token用于判断是否登录 | |
| 166 | - isThirdLoginAndNoDind: true, //用于判断是否是第三方登录并且不需要绑定账号 | |
| 167 | - thirdUserId: res.thirdUserId, | |
| 168 | - }; | |
| 169 | - //设置全局变量openId | |
| 170 | - getApp().globalData.openId = res.thirdUserId; | |
| 171 | - if (userInfo.token) { | |
| 172 | - this.setUserInfo(userInfo); | |
| 173 | - } | |
| 174 | - uni | |
| 175 | - .showToast({ | |
| 176 | - title: "第三方账号登录成功", | |
| 177 | - icon: "none", | |
| 178 | - }) | |
| 179 | - .then(async (res) => { | |
| 180 | - this.saveUserInfo(); | |
| 181 | - await this.getAlarmTotalData(); | |
| 182 | - uni.reLaunch({ | |
| 183 | - url: "/pages/personal/personal", | |
| 184 | - }); | |
| 185 | - }); | |
| 186 | - } | |
| 187 | - } | |
| 188 | - }, | |
| 189 | - fail: (res) => { | |
| 190 | - //拒绝授权 | |
| 191 | - return; | |
| 192 | - }, | |
| 193 | - }); | |
| 194 | - }, | |
| 195 | - //#endif | |
| 196 | - //#ifdef APP-PLUS | |
| 197 | - // handleAppPlusAuthorization() { | |
| 198 | - // var that = this; | |
| 199 | - // uni.getProvider({ | |
| 200 | - // service: 'oauth', | |
| 201 | - // success: function(res) { | |
| 202 | - // if (~res.provider.indexOf('weixin')) { | |
| 203 | - // uni.login({ | |
| 204 | - // provider: 'weixin', | |
| 205 | - // success: function(loginRes) { | |
| 206 | - // // loginRes 包含access_token,expires_in,openid,unionid等信息 | |
| 207 | - // uni.showToast({ | |
| 208 | - // title: "第三方账号登录成功", | |
| 209 | - // icon: "none", | |
| 210 | - // }) | |
| 211 | - // }, | |
| 212 | - // fail: function(res) { | |
| 213 | - // // that.$refs.uToast.show({ | |
| 214 | - // // title: '微信登录失败', | |
| 215 | - // // type: 'warning' | |
| 216 | - // // }); | |
| 217 | - // } | |
| 218 | - // }); | |
| 219 | - // } | |
| 220 | - // } | |
| 221 | - // }); | |
| 222 | - // }, | |
| 223 | - //#endif | |
| 224 | - async saveUserInfo() { | |
| 225 | - const userInfoRes = await api.loginApi.setUserInfoApi() | |
| 226 | - const plateInfoRes = await api.loginApi.setPlateInfoApi() | |
| 227 | - if (userInfoRes) { | |
| 228 | - this.setUserInfo(userInfoRes); | |
| 229 | - } | |
| 230 | - if (plateInfoRes) { | |
| 231 | - this.setPlateInfo(plateInfoRes); | |
| 232 | - } | |
| 233 | - }, | |
| 234 | - async getAlarmTotalData() { | |
| 235 | - const res = await api.loginApi.getAlarmTotalApi() | |
| 236 | - if (res) { | |
| 237 | - this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 238 | - } | |
| 239 | - }, | |
| 240 | - async onSubmitFunc() { | |
| 241 | - if (this.loginForm.username == "") { | |
| 242 | - return uni.$u.toast("请输入登录账号~"); | |
| 243 | - } | |
| 244 | - if (this.loginForm.password == "") { | |
| 245 | - uni.showToast({ | |
| 246 | - title: "请输入登录密码~", | |
| 247 | - icon: "none", | |
| 248 | - }); | |
| 249 | - return; | |
| 250 | - } else if (!loginPasswordReg.test(this.loginForm.password)) { | |
| 251 | - uni.showModal({ | |
| 252 | - title: "提示", | |
| 253 | - content: "密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~", | |
| 254 | - showCancel: false, | |
| 255 | - }); | |
| 256 | - return; | |
| 257 | - } | |
| 258 | - const res = await api.loginApi.postLoginApi(this.loginForm) | |
| 259 | - if (res) { | |
| 260 | - // 储存登录信息 | |
| 261 | - let resObj = { | |
| 262 | - refreshToken: res.refreshToken, | |
| 263 | - isToken: res.token, | |
| 264 | - }; | |
| 265 | - let userInfo = { | |
| 266 | - ...resObj, | |
| 267 | - token: true, //token用于判断是否登录 | |
| 268 | - isThirdLogin: false, | |
| 269 | - isThirdLoginAndNoDind: false, | |
| 270 | - }; | |
| 271 | - if (userInfo.token) { | |
| 272 | - this.setUserInfo(userInfo); | |
| 273 | - } | |
| 274 | - uni | |
| 275 | - .showToast({ | |
| 276 | - title: "登录成功~", | |
| 277 | - icon: "none", | |
| 278 | - }) | |
| 279 | - .then(async (res) => { | |
| 280 | - await this.saveUserInfo(); | |
| 281 | - await this.getAlarmTotalData(); | |
| 282 | - uni.reLaunch({ | |
| 283 | - url: "/pages/personal/personal", | |
| 284 | - }); | |
| 285 | - }); | |
| 286 | - } | |
| 287 | - }, | |
| 288 | - openCodeFunc() { | |
| 289 | - uni.navigateTo({ | |
| 290 | - url: "../other/code", | |
| 291 | - }); | |
| 292 | - }, | |
| 293 | - findPassrordFunc() { | |
| 294 | - uni.navigateTo({ | |
| 295 | - url: "../other/findPassword", | |
| 296 | - }); | |
| 297 | - }, | |
| 298 | - showPasswordMode() { | |
| 299 | - this.showPassword = !this.showPassword; | |
| 300 | - }, | |
| 301 | - }, | |
| 302 | - }; | |
| 303 | -</script> | |
| 304 | - | |
| 305 | -<style lang="scss" scoped> | |
| 306 | - @import "./static/login.scss"; | |
| 307 | - | |
| 308 | - /deep/ button { | |
| 309 | - background: rgba(0, 0, 0, 0); | |
| 310 | - } | |
| 311 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="login-page" :style="{backgroundImage:setLoginBg}"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view class="u-flex login-main"> | |
| 6 | + <view class="content"> | |
| 7 | + <view class="hello login-text-muted">您好,</view> | |
| 8 | + <view style="width: 587rpx;" class="text-clip hello-welcome login-text-muted">欢迎来到{{setHeadTitle}}! | |
| 9 | + </view> | |
| 10 | + </view> | |
| 11 | + </view> | |
| 12 | + <view class="login-body"> | |
| 13 | + <view class="login-phone"> | |
| 14 | + <view class="form-row u-flex"> | |
| 15 | + <u-input :adjust-position="false" v-model="loginForm.username" type="text" placeholder="请输入登录账号" | |
| 16 | + border="bottom" /> | |
| 17 | + </view> | |
| 18 | + <view class="form-row u-flex"> | |
| 19 | + <u-input :adjust-position="false" v-model="loginForm.password" :password="showPassword" | |
| 20 | + placeholder="请输入登录密码" border="bottom"> | |
| 21 | + <template slot="suffix"> | |
| 22 | + <view @click="showPasswordMode" style="padding: 10rpx"> | |
| 23 | + <u-icon width="18" height="14" :name="passwordIcon"></u-icon> | |
| 24 | + </view> | |
| 25 | + </template> | |
| 26 | + </u-input> | |
| 27 | + </view> | |
| 28 | + <button class="submit" size="default" @click="onSubmitFunc"> | |
| 29 | + <text class="text">登录</text> | |
| 30 | + </button> | |
| 31 | + <view class="u-flex row-item"> | |
| 32 | + <view class="row-phone login-text-gray" @click="openCodeFunc">手机验证码登录</view> | |
| 33 | + <view class="row-reset login-text-gray" @click="findPassrordFunc">忘记密码</view> | |
| 34 | + </view> | |
| 35 | + <view class="u-flex link-login"> | |
| 36 | + <!-- #ifdef MP-WEIXIN --> | |
| 37 | + <view class="link-text login-text-gray">第三方账号登录</view> | |
| 38 | + <view style="height: 20rpx"></view> | |
| 39 | + <button class="link-image" @tap="handleWenxinAuthorization"> | |
| 40 | + <image class="image" src="/static/weixin.png" mode="aspectFill"></image> | |
| 41 | + </button> | |
| 42 | + <!-- #endif --> | |
| 43 | + </view> | |
| 44 | + </view> | |
| 45 | + </view> | |
| 46 | + </view> | |
| 47 | +</template> | |
| 48 | + | |
| 49 | +<script> | |
| 50 | + import {mapMutations,mapActions,mapState} from "vuex"; | |
| 51 | + import api from '@/api' | |
| 52 | + import {loginPasswordReg,useReLaunch,useShowToast,useShowModal,useNavigateTo} from '@/plugins/utils.js' | |
| 53 | + | |
| 54 | + export default { | |
| 55 | + data() { | |
| 56 | + return { | |
| 57 | + loginForm: { | |
| 58 | + username: "fengtao", | |
| 59 | + password: "Aa123456@", | |
| 60 | + }, | |
| 61 | + showPassword: true, | |
| 62 | + code: "", | |
| 63 | + openid: "", | |
| 64 | + mpOwnConfig: {}, | |
| 65 | + defaultLogo: "/static/login.png", | |
| 66 | + }; | |
| 67 | + }, | |
| 68 | + onLoad() { | |
| 69 | + //#ifdef MP-WEIXIN | |
| 70 | + wx.login({ | |
| 71 | + success: (res) => { | |
| 72 | + if (!res.code) return | |
| 73 | + this.code = res.code; | |
| 74 | + }, | |
| 75 | + }); | |
| 76 | + //#endif | |
| 77 | + uni.setStorageSync('getConfiguration', { | |
| 78 | + isConfiguration: false | |
| 79 | + }); | |
| 80 | + this.getPlateForm(); | |
| 81 | + }, | |
| 82 | + computed: { | |
| 83 | + passwordIcon() { | |
| 84 | + return this.showPassword ? '/static/eye-hide.png' : '/static/eye.png' | |
| 85 | + }, | |
| 86 | + setHeadTitle() { | |
| 87 | + return this.mpOwnConfig.name !== undefined ? this.mpOwnConfig.name : "ThingsKit" | |
| 88 | + }, | |
| 89 | + setLoginBg() { | |
| 90 | + return 'url(' + (this.mpOwnConfig.bg !== undefined ? this.mpOwnConfig.bg : `${this.defaultLogo}`) + ')' | |
| 91 | + } | |
| 92 | + }, | |
| 93 | + onShow() { | |
| 94 | + uni.setStorageSync('getConfiguration', { | |
| 95 | + isConfiguration: false | |
| 96 | + }); | |
| 97 | + }, | |
| 98 | + methods: { | |
| 99 | + ...mapState(["plateInfo"]), | |
| 100 | + ...mapMutations(["setUserInfo", "setPlateInfo"]), | |
| 101 | + ...mapActions(["updateBadgeTotal"]), | |
| 102 | + //获取平台定制信息 | |
| 103 | + async getPlateForm() { | |
| 104 | + const res = await api.loginApi.getPlateCustomApi() | |
| 105 | + if (!res) return | |
| 106 | + this.mpOwnConfig = { | |
| 107 | + bg: res.background, | |
| 108 | + logo: res.logo, | |
| 109 | + name: res.name, | |
| 110 | + }; | |
| 111 | + }, | |
| 112 | + saveLoginInfo(res, isThirdLoginAndNoDind, isThirdLogin, toastText) { | |
| 113 | + let tokenInfo = { | |
| 114 | + refreshToken: res.refreshToken, | |
| 115 | + isToken: res.token, | |
| 116 | + }; | |
| 117 | + let userInfo = { | |
| 118 | + ...tokenInfo, | |
| 119 | + token: true, //token用于判断是否登录 | |
| 120 | + isThirdLoginAndNoDind, //用于判断是否是第三方登录并且不需要绑定账号 | |
| 121 | + isThirdLogin, //用于判断是否是第三方登录并且需要绑定账号 | |
| 122 | + thirdUserId: res.thirdUserId, | |
| 123 | + }; | |
| 124 | + //设置全局变量openId | |
| 125 | + getApp().globalData.openId = res.thirdUserId; | |
| 126 | + if (userInfo.token) { | |
| 127 | + this.setUserInfo(userInfo); | |
| 128 | + } | |
| 129 | + useShowToast(toastText).then(async (res) => { | |
| 130 | + this.saveUserInfo(); | |
| 131 | + await this.getAlarmTotalData(); | |
| 132 | + useReLaunch("../../pages/index/index") | |
| 133 | + }); | |
| 134 | + }, | |
| 135 | + //微信授权登录 | |
| 136 | + //#ifdef MP-WEIXIN | |
| 137 | + handleWenxinAuthorization() { | |
| 138 | + wx.getUserProfile({ | |
| 139 | + desc: "微信第三方授权", | |
| 140 | + success: async (reswenxin) => { | |
| 141 | + if ( | |
| 142 | + reswenxin.errMsg === "getUserProfile:ok" && | |
| 143 | + reswenxin.encryptedData | |
| 144 | + ) { | |
| 145 | + //获取用户信息 | |
| 146 | + let wenxinUserInfo = { | |
| 147 | + avatarUrl: reswenxin.userInfo.avatarUrl, | |
| 148 | + thirdUserId: this.openid, | |
| 149 | + }; | |
| 150 | + const res = await api.loginApi.getThirdLoginApi(this.code) | |
| 151 | + if (!res.token && res.thirdUserId) { | |
| 152 | + //需要进行三方绑定 | |
| 153 | + let userInfo = { | |
| 154 | + isThirdLogin: true, //用于判断是否是第三方登录并且需要绑定账号 | |
| 155 | + avatar: wenxinUserInfo.avatarUrl, | |
| 156 | + thirdUserId: res.thirdUserId, | |
| 157 | + }; | |
| 158 | + this.setUserInfo(userInfo); | |
| 159 | + //设置全局变量openId | |
| 160 | + getApp().globalData.openId = res.thirdUserId; | |
| 161 | + useReLaunch("/pages/index/index") | |
| 162 | + } else { | |
| 163 | + // 不需要绑定,直接第三方登录使用 | |
| 164 | + this.saveLoginInfo(res, true, null, "第三方账号登录成功") | |
| 165 | + } | |
| 166 | + } | |
| 167 | + }, | |
| 168 | + fail: (res) => { | |
| 169 | + //拒绝授权 | |
| 170 | + return; | |
| 171 | + }, | |
| 172 | + }); | |
| 173 | + }, | |
| 174 | + //#endif | |
| 175 | + async saveUserInfo() { | |
| 176 | + const userInfoRes = await api.loginApi.setUserInfoApi() | |
| 177 | + const plateInfoRes = await api.loginApi.setPlateInfoApi() | |
| 178 | + Promise.all([userInfoRes, plateInfoRes]).then(res => { | |
| 179 | + this.setUserInfo(res[0]) | |
| 180 | + this.setPlateInfo(res[1]) | |
| 181 | + }) | |
| 182 | + }, | |
| 183 | + async getAlarmTotalData() { | |
| 184 | + const res = await api.loginApi.getAlarmTotalApi() | |
| 185 | + if (!res) return | |
| 186 | + this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 187 | + }, | |
| 188 | + async onSubmitFunc() { | |
| 189 | + const validateValue = Object.values(this.loginForm) | |
| 190 | + if (!validateValue[0]) return uni.$u.toast("请输入登录账号~"); | |
| 191 | + if (!validateValue[1]) return uni.$u.toast("请输入登录密码~"); | |
| 192 | + if (!loginPasswordReg.test(validateValue[1])) return useShowModal( | |
| 193 | + "密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~", ) | |
| 194 | + const res = await api.loginApi.postLoginApi(this.loginForm) | |
| 195 | + if (res) { | |
| 196 | + // 储存登录信息 | |
| 197 | + this.saveLoginInfo(res, false, false, "登录成功~") | |
| 198 | + } | |
| 199 | + }, | |
| 200 | + openCodeFunc() { | |
| 201 | + useNavigateTo("../other/code") | |
| 202 | + }, | |
| 203 | + findPassrordFunc() { | |
| 204 | + useNavigateTo("../other/find-password") | |
| 205 | + }, | |
| 206 | + showPasswordMode() { | |
| 207 | + this.showPassword = !this.showPassword; | |
| 208 | + }, | |
| 209 | + }, | |
| 210 | + }; | |
| 211 | +</script> | |
| 212 | + | |
| 213 | +<style lang="scss" scoped> | |
| 214 | + @import "./static/login.scss"; | |
| 215 | + | |
| 216 | + /deep/ button { | |
| 217 | + background: rgba(0, 0, 0, 0); | |
| 218 | + } | |
| 219 | +</style> | |
| \ No newline at end of file | ... | ... |
login-subpackage/public/static/login.scss
renamed from
publicLoginSubPage/public/static/login.scss
| 1 | -.login-page { | |
| 2 | - min-height: 100vh; | |
| 3 | - width: 750rpx; | |
| 4 | - background: url(/static/login.png) no-repeat; | |
| 5 | - background-size: 100% 100%; | |
| 6 | - .login-main { | |
| 7 | - flex-direction: column; | |
| 8 | - .content { | |
| 9 | - height: 250rpx; | |
| 10 | - margin-top: 90rpx; | |
| 11 | - margin-left: -107rpx; | |
| 12 | - position: relative; | |
| 13 | - top: 50rpx; | |
| 14 | - left: -15rpx; | |
| 15 | - .hello { | |
| 16 | - font-size: 30px; | |
| 17 | - color: #3a4759; | |
| 18 | - z-index: 9999; | |
| 19 | - position: relative; | |
| 20 | - } | |
| 21 | - .hello-welcome { | |
| 22 | - position: relative; | |
| 23 | - font-size: 30px; | |
| 24 | - color: #3a4759; | |
| 25 | - z-index: 9999; | |
| 26 | - } | |
| 27 | - } | |
| 28 | - } | |
| 29 | -} | |
| 30 | - | |
| 31 | -.f__login { | |
| 32 | - padding: 8rpx 32rpx; | |
| 33 | - border-radius: 18rpx 18rpx 0 0; | |
| 34 | - z-index: 99; | |
| 35 | - position: relative; | |
| 36 | -} | |
| 37 | - | |
| 38 | -.loginPhone { | |
| 39 | - .form-row { | |
| 40 | - justify-content: space-between; | |
| 41 | - margin-top: 30rpx; | |
| 42 | - } | |
| 43 | - | |
| 44 | - .submit { | |
| 45 | - margin-top: 60rpx; | |
| 46 | - background: linear-gradient(90deg, #5dc2fc 0%, #377dff 100%); | |
| 47 | - width: 100%; | |
| 48 | - border-radius: 46px; | |
| 49 | - .text { | |
| 50 | - color: #ffffff; | |
| 51 | - } | |
| 52 | - } | |
| 53 | - .row-item { | |
| 54 | - flex-direction: row; | |
| 55 | - margin-top: 60rpx; | |
| 56 | - justify-content: space-between; | |
| 57 | - .row-phone { | |
| 58 | - color: #999999; | |
| 59 | - font-size: 13px; | |
| 60 | - } | |
| 61 | - .row-reset { | |
| 62 | - color: #999999; | |
| 63 | - font-size: 13px; | |
| 64 | - position: relative; | |
| 65 | - } | |
| 66 | - } | |
| 67 | - .link-login { | |
| 68 | - justify-content: center; | |
| 69 | - flex-direction: column; | |
| 70 | - margin-top: 370rpx; | |
| 71 | - /* #ifdef APP-PLUS */ | |
| 72 | - margin-top: 250rpx; | |
| 73 | - /* #endif */ | |
| 74 | - .link-text { | |
| 75 | - color: #999999; | |
| 76 | - font-size: 13px; | |
| 77 | - } | |
| 78 | - .link-image { | |
| 79 | - .image { | |
| 80 | - width: 75rpx; | |
| 81 | - height: 75rpx; | |
| 82 | - } | |
| 83 | - } | |
| 84 | - } | |
| 1 | +.login-page { | |
| 2 | + min-height: 100vh; | |
| 3 | + width: 750rpx; | |
| 4 | + background: url(/static/login.png) no-repeat; | |
| 5 | + background-size: 100% 100%; | |
| 6 | + .login-main { | |
| 7 | + flex-direction: column; | |
| 8 | + .content { | |
| 9 | + height: 250rpx; | |
| 10 | + margin-top: 90rpx; | |
| 11 | + margin-left: -107rpx; | |
| 12 | + position: relative; | |
| 13 | + top: 50rpx; | |
| 14 | + left: -15rpx; | |
| 15 | + .hello { | |
| 16 | + font-size: 30px; | |
| 17 | + color: #3a4759; | |
| 18 | + z-index: 9999; | |
| 19 | + position: relative; | |
| 20 | + } | |
| 21 | + .hello-welcome { | |
| 22 | + position: relative; | |
| 23 | + font-size: 30px; | |
| 24 | + color: #3a4759; | |
| 25 | + z-index: 9999; | |
| 26 | + } | |
| 27 | + } | |
| 28 | + } | |
| 29 | +} | |
| 30 | + | |
| 31 | +.login-body { | |
| 32 | + padding: 8rpx 32rpx; | |
| 33 | + border-radius: 18rpx 18rpx 0 0; | |
| 34 | + z-index: 99; | |
| 35 | + position: relative; | |
| 36 | +} | |
| 37 | + | |
| 38 | +.login-phone { | |
| 39 | + .form-row { | |
| 40 | + justify-content: space-between; | |
| 41 | + margin-top: 30rpx; | |
| 42 | + } | |
| 43 | + | |
| 44 | + .submit { | |
| 45 | + margin-top: 60rpx; | |
| 46 | + background: linear-gradient(90deg, #5dc2fc 0%, #377dff 100%); | |
| 47 | + width: 100%; | |
| 48 | + border-radius: 46px; | |
| 49 | + .text { | |
| 50 | + color: #ffffff; | |
| 51 | + } | |
| 52 | + } | |
| 53 | + .row-item { | |
| 54 | + flex-direction: row; | |
| 55 | + margin-top: 60rpx; | |
| 56 | + justify-content: space-between; | |
| 57 | + .row-phone { | |
| 58 | + color: #999999; | |
| 59 | + font-size: 13px; | |
| 60 | + } | |
| 61 | + .row-reset { | |
| 62 | + color: #999999; | |
| 63 | + font-size: 13px; | |
| 64 | + position: relative; | |
| 65 | + } | |
| 66 | + } | |
| 67 | + .link-login { | |
| 68 | + justify-content: center; | |
| 69 | + flex-direction: column; | |
| 70 | + margin-top: 370rpx; | |
| 71 | + /* #ifdef APP-PLUS */ | |
| 72 | + margin-top: 250rpx; | |
| 73 | + /* #endif */ | |
| 74 | + .link-text { | |
| 75 | + color: #999999; | |
| 76 | + font-size: 13px; | |
| 77 | + } | |
| 78 | + .link-image { | |
| 79 | + .image { | |
| 80 | + width: 75rpx; | |
| 81 | + height: 75rpx; | |
| 82 | + } | |
| 83 | + } | |
| 84 | + } | |
| 85 | 85 | } | ... | ... |
| ... | ... | @@ -4,7 +4,7 @@ import App from './App' |
| 4 | 4 | // 工具 |
| 5 | 5 | import '@/plugins/utils.js'; |
| 6 | 6 | |
| 7 | -//权限配置中心 | |
| 7 | +//服务端路径配置中心 | |
| 8 | 8 | import base from '@/config/baseUrl' |
| 9 | 9 | Vue.prototype.$base = base; |
| 10 | 10 | |
| ... | ... | @@ -22,13 +22,15 @@ import f_show_modal from '@/components/module/show_modal/f_show_modal.js' |
| 22 | 22 | Vue.use(f_show_modal) |
| 23 | 23 | // #endif |
| 24 | 24 | |
| 25 | -// uview | |
| 25 | +// uview库 | |
| 26 | 26 | import uView from '@/uni_modules/uview-ui' |
| 27 | 27 | Vue.use(uView) |
| 28 | 28 | |
| 29 | -// 公共组件 | |
| 29 | +// 公共组件注册 | |
| 30 | 30 | import publicModule from "@/components/common/public-module.vue"; |
| 31 | 31 | Vue.component("public-module", publicModule); |
| 32 | +import headerSearch from "@/components/common/header-search.vue"; | |
| 33 | +Vue.component("header-search", headerSearch); | |
| 32 | 34 | |
| 33 | 35 | Vue.config.productionTip = false |
| 34 | 36 | App.mpType = 'app' | ... | ... |
| ... | ... | @@ -26,24 +26,12 @@ |
| 26 | 26 | } |
| 27 | 27 | }, |
| 28 | 28 | { |
| 29 | - "path": "pages/device/org/org", | |
| 30 | - "style": { | |
| 31 | - "navigationBarTitleText": "组织筛选" | |
| 32 | - } | |
| 33 | - }, | |
| 34 | - { | |
| 35 | 29 | "path": "pages/alarm/alarm", |
| 36 | 30 | "style": { |
| 37 | 31 | "navigationBarTitleText": "告警" |
| 38 | 32 | } |
| 39 | 33 | }, |
| 40 | 34 | { |
| 41 | - "path": "pages/alarm/org/org", | |
| 42 | - "style": { | |
| 43 | - "navigationBarTitleText": "组织筛选" | |
| 44 | - } | |
| 45 | - }, | |
| 46 | - { | |
| 47 | 35 | "path": "pages/personal/personal", |
| 48 | 36 | "style": { |
| 49 | 37 | "navigationBarTitleText": "个人中心", |
| ... | ... | @@ -51,55 +39,55 @@ |
| 51 | 39 | } |
| 52 | 40 | }, |
| 53 | 41 | { |
| 54 | - "path": "pages/index/camera/camera", | |
| 42 | + "path": "pages/index/components/camera/camera", | |
| 55 | 43 | "style": { |
| 56 | 44 | "navigationBarTitleText": "查看摄像头" |
| 57 | 45 | } |
| 58 | 46 | }, |
| 59 | 47 | { |
| 60 | - "path": "pages/index/camera/org/org", | |
| 61 | - "style": { | |
| 62 | - "navigationBarTitleText": "组织筛选" | |
| 63 | - } | |
| 64 | - }, { | |
| 65 | - "path": "pages/index/configuration/configuration", | |
| 48 | + "path": "pages/index/components/configuration/configuration", | |
| 66 | 49 | "style": { |
| 67 | 50 | "navigationBarTitleText": "查看组态" |
| 68 | 51 | } |
| 69 | - | |
| 70 | 52 | }, |
| 71 | 53 | { |
| 72 | - "path": "pages/index/configuration/configurationDetail", | |
| 54 | + "path": "pages/index/components/configuration/configuration-detail", | |
| 73 | 55 | "style": { |
| 74 | 56 | "navigationBarTitleText": "组态详情" |
| 75 | 57 | } |
| 58 | + }, | |
| 59 | + { | |
| 60 | + "path": "pages/organization/organization", | |
| 61 | + "style": { | |
| 62 | + "navigationBarTitleText": "组织筛选" | |
| 63 | + } | |
| 76 | 64 | } |
| 77 | 65 | ], |
| 78 | 66 | "subPackages": [{ |
| 79 | - "root": "alarmSubPage", | |
| 67 | + "root": "alarm-subpackage", | |
| 80 | 68 | "pages": [{ |
| 81 | - "path": "alarmDetailPage/alarmDetail", | |
| 69 | + "path": "alarm-detail/alarm-detail", | |
| 82 | 70 | "style": { |
| 83 | 71 | "navigationBarTitleText": "告警详情" |
| 84 | 72 | } |
| 85 | 73 | }] |
| 86 | 74 | }, |
| 87 | 75 | { |
| 88 | - "root": "deviceSubPage", | |
| 76 | + "root": "device-subpackage", | |
| 89 | 77 | "pages": [{ |
| 90 | - "path": "deviceDetailPage/deviceDetail", | |
| 78 | + "path": "device-detail/device-detail", | |
| 91 | 79 | "style": { |
| 92 | 80 | "navigationBarTitleText": "设备详情" |
| 93 | 81 | } |
| 94 | 82 | }, |
| 95 | 83 | { |
| 96 | - "path": "deviceDetailPage/tabDetail/CommandDetail", | |
| 84 | + "path": "device-detail/components/command-detail", | |
| 97 | 85 | "style": { |
| 98 | 86 | "navigationBarTitleText": "命令详情" |
| 99 | 87 | } |
| 100 | 88 | }, |
| 101 | 89 | { |
| 102 | - "path": "deviceDetailPage/devicePosition", | |
| 90 | + "path": "device-detail/device-position", | |
| 103 | 91 | "style": { |
| 104 | 92 | "navigationBarTitleText": "设备地理位置" |
| 105 | 93 | }, |
| ... | ... | @@ -115,15 +103,15 @@ |
| 115 | 103 | ] |
| 116 | 104 | }, |
| 117 | 105 | { |
| 118 | - "root": "sysNotifySubPage", | |
| 106 | + "root": "sysnotify-subpackage", | |
| 119 | 107 | "pages": [{ |
| 120 | - "path": "sysNotifyPage/systemNotify", | |
| 108 | + "path": "sys-notify/system-notify", | |
| 121 | 109 | "style": { |
| 122 | 110 | "navigationBarTitleText": "系统通知" |
| 123 | 111 | } |
| 124 | 112 | }, |
| 125 | 113 | { |
| 126 | - "path": "sysNotifyPage/notifyDetail", | |
| 114 | + "path": "sys-notify/notify-detail", | |
| 127 | 115 | "style": { |
| 128 | 116 | "navigationBarTitleText": "通知详情" |
| 129 | 117 | } |
| ... | ... | @@ -131,7 +119,7 @@ |
| 131 | 119 | ] |
| 132 | 120 | }, |
| 133 | 121 | { |
| 134 | - "root": "feedBackSubPage", | |
| 122 | + "root": "feedback-subpackage", | |
| 135 | 123 | "pages": [{ |
| 136 | 124 | "path": "feedback/feedback", |
| 137 | 125 | "style": { |
| ... | ... | @@ -140,7 +128,7 @@ |
| 140 | 128 | }] |
| 141 | 129 | }, |
| 142 | 130 | { |
| 143 | - "root": "publicLoginSubPage", | |
| 131 | + "root": "login-subpackage", | |
| 144 | 132 | "pages": [{ |
| 145 | 133 | "path": "public/login", |
| 146 | 134 | "style": { |
| ... | ... | @@ -156,11 +144,11 @@ |
| 156 | 144 | { |
| 157 | 145 | "path": "other/code", |
| 158 | 146 | "style": { |
| 159 | - "navigationBarTitleText": "验证码登录" | |
| 147 | + "navigationBarTitleText": "手机验证码登录" | |
| 160 | 148 | } |
| 161 | 149 | }, |
| 162 | 150 | { |
| 163 | - "path": "other/findPassword", | |
| 151 | + "path": "other/find-password", | |
| 164 | 152 | "style": { |
| 165 | 153 | "navigationBarTitleText": "忘记密码" |
| 166 | 154 | } |
| ... | ... | @@ -170,7 +158,7 @@ |
| 170 | 158 | ], |
| 171 | 159 | "globalStyle": { |
| 172 | 160 | "navigationBarTextStyle": "black", |
| 173 | - "navigationBarTitleText": "云腾app", | |
| 161 | + "navigationBarTitleText": "ThingsKit", | |
| 174 | 162 | "navigationBarBackgroundColor": "#FFFFFF", |
| 175 | 163 | "backgroundColor": "#FFFFFF", |
| 176 | 164 | "backgroundColorTop": "#FFFFFF" |
| ... | ... | @@ -206,4 +194,4 @@ |
| 206 | 194 | } |
| 207 | 195 | ] |
| 208 | 196 | } |
| 209 | -} | |
| 197 | +} | |
| \ No newline at end of file | ... | ... |
| 1 | -<template> | |
| 2 | - <view class="alert-page" :class="show ? 'pop-no-scroll' : ''"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <!-- 吸顶组件 --> | |
| 6 | - <u-sticky> | |
| 7 | - <view class="device-top"> | |
| 8 | - <view class="search"> | |
| 9 | - <view> | |
| 10 | - <view class="search-left"> | |
| 11 | - <u--input prefixIcon="search" placeholder="请输入告警设备" shape="circle" @change="inputChanged"> | |
| 12 | - </u--input> | |
| 13 | - </view> | |
| 14 | - </view> | |
| 15 | - <view @click="openSearchDialog" class="search-right"> | |
| 16 | - <text>筛选</text> | |
| 17 | - <image src="../../static/shaixuan.png" /> | |
| 18 | - </view> | |
| 19 | - </view> | |
| 20 | - <u-line /> | |
| 21 | - <view class="org"> | |
| 22 | - <u-cell @click="openOrg" isLink title="组织关系" :border="false"> | |
| 23 | - <view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;"> | |
| 24 | - <image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image> | |
| 25 | - <view style="margin-left: 10rpx; color: #666;"> | |
| 26 | - 告警数: | |
| 27 | - <text style="margin-left: 20rpx;">{{ alertTotal }}</text> | |
| 28 | - </view> | |
| 29 | - </view> | |
| 30 | - </u-cell> | |
| 31 | - </view> | |
| 32 | - </view> | |
| 33 | - </u-sticky> | |
| 34 | - <!-- 吸顶组件 --> | |
| 35 | - <!-- 自带分页组件 --> | |
| 36 | - <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 37 | - @up="upCallback"> | |
| 38 | - <view class="device-list"> | |
| 39 | - <view @click="openAlertDetail(item)" class="list-item" v-for="(item, index) in list" :key="index"> | |
| 40 | - <view class="u-flex item"> | |
| 41 | - <view class="item-text text-clip"> | |
| 42 | - <text class="text-bold">{{ item.deviceName == null ? '暂无数据' : item.deviceName }}</text> | |
| 43 | - </view> | |
| 44 | - <view class="item-text text-clip"> | |
| 45 | - <text | |
| 46 | - class="text-muted">{{ item.details == null ? '暂无数据' : formatDetailText(item.details.data) }}</text> | |
| 47 | - </view> | |
| 48 | - <view class="item-text"> | |
| 49 | - <text class="text-muted"> | |
| 50 | - 告警状态:{{ | |
| 51 | - item.status == 'CLEARED_UNACK' | |
| 52 | - ? '清除未确认' | |
| 53 | - : item.status == 'ACTIVE_UNACK' | |
| 54 | - ? '激活未确认' | |
| 55 | - : item.status == 'CLEARED_ACK' | |
| 56 | - ? '清除已确认' | |
| 57 | - : '激活已确认' | |
| 58 | - }} | |
| 59 | - </text> | |
| 60 | - </view> | |
| 61 | - <view class="item-text"> | |
| 62 | - <text class="text-secondary">{{ item.createdTime }}</text> | |
| 63 | - </view> | |
| 64 | - </view> | |
| 65 | - <view class="item"> | |
| 66 | - <view class="u-flex item-right"> | |
| 67 | - <image class="right-image" :src="bindImageUrl(item.severity)"></image> | |
| 68 | - <view class="right-text"> | |
| 69 | - <text class="text-no-color" :style="[ | |
| 70 | - item.severity == 'CRITICAL' | |
| 71 | - ? { color: '#DE4437' } | |
| 72 | - : item.severity == 'MAJOR' | |
| 73 | - ? { color: '#DE7337' } | |
| 74 | - : item.severity == 'MINOR' | |
| 75 | - ? { color: '#FFC107' } | |
| 76 | - : item.severity == 'WARNING' | |
| 77 | - ? { color: '#DE4437' } | |
| 78 | - : { color: '#00C9A7' } | |
| 79 | - ]"> | |
| 80 | - {{ | |
| 81 | - item.severity == 'CRITICAL' | |
| 82 | - ? '危险' | |
| 83 | - : item.severity == 'MAJOR' | |
| 84 | - ? '重要' | |
| 85 | - : item.severity == 'MINOR' | |
| 86 | - ? '次要' | |
| 87 | - : item.severity == 'WARNING' | |
| 88 | - ? '警告' | |
| 89 | - : '不确定' | |
| 90 | - }} | |
| 91 | - </text> | |
| 92 | - </view> | |
| 93 | - </view> | |
| 94 | - </view> | |
| 95 | - </view> | |
| 96 | - </view> | |
| 97 | - <mescroll-empty v-if="!list.length" /> | |
| 98 | - </mescroll-body> | |
| 99 | - <!-- 自带分页组件 --> | |
| 100 | - <view style="height: 20rpx"></view> | |
| 101 | - <!-- 告警筛选--> | |
| 102 | - <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom"> | |
| 103 | - <view class="popup-page"> | |
| 104 | - <view class="popup-text"><text class="text">告警筛选</text></view> | |
| 105 | - <view class="popup-alarm-page u-flex"> | |
| 106 | - <view> | |
| 107 | - <view class="popup-alarm-text"><text class="text">告警状态</text></view> | |
| 108 | - <view class="u-flex popup-alarm-child"> | |
| 109 | - <view class="alarm-text" @click="getAlertStatus(item, index)" | |
| 110 | - :style="[index == current1 ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } : { background: '#F6F6F6' }]" | |
| 111 | - v-for="(item, index) in alertStatus" :key="index"> | |
| 112 | - <text :class="[index == current1 ? 'select-text' : 'un-select-text']" | |
| 113 | - class="text">{{ item.name }}</text> | |
| 114 | - </view> | |
| 115 | - </view> | |
| 116 | - <view style="margin-top: 169rpx;"> | |
| 117 | - <view class="popup-alarm-text"><text class="text">设备类型</text></view> | |
| 118 | - <view class="u-flex popup-alarm-child"> | |
| 119 | - <view class="alarm-text" @click="getTypeStatus(item, index)" :style="[ | |
| 120 | - index == current2 ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } : { background: '#F6F6F6' } | |
| 121 | - ]" v-for="(item, index) in deviceType" :key="index"> | |
| 122 | - <text :class="[index == current2 ? 'select-text' : 'un-select-text']" | |
| 123 | - class="text">{{ item.name }}</text> | |
| 124 | - </view> | |
| 125 | - </view> | |
| 126 | - | |
| 127 | - <view style="margin-top: 169rpx;"> | |
| 128 | - <view class="popup-alarm-text"><text class="text">告警等级</text></view> | |
| 129 | - <view class="u-flex popup-alarm-child"> | |
| 130 | - <view class="alarm-text" @click="getLevelStatus(item, index)" :style="[ | |
| 131 | - index == current3 ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } : { background: '#F6F6F6' } | |
| 132 | - ]" v-for="(item, index) in alertLevel" :key="index"> | |
| 133 | - <text :class="[index == current3 ? 'select-text' : 'un-select-text']" | |
| 134 | - class="text">{{ item.name }}</text> | |
| 135 | - </view> | |
| 136 | - </view> | |
| 137 | - <view style="margin-top: 169rpx;"> | |
| 138 | - <view class="popup-alarm-text"><text class="text">选择时间</text></view> | |
| 139 | - <view class="u-flex popup-alarm-child"> | |
| 140 | - <view class="alarm-text" @click="getTimeStatus(item, index)" :style="[ | |
| 141 | - index == current4 | |
| 142 | - ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } | |
| 143 | - : { background: '#F6F6F6' } | |
| 144 | - ]" v-for="(item, index) in timeArea" :key="index"> | |
| 145 | - <text :class="[index == current4 ? 'select-text' : 'un-select-text']" | |
| 146 | - class="text">{{ item.name }}</text> | |
| 147 | - </view> | |
| 148 | - </view> | |
| 149 | - <view style="margin-top: 169rpx;margin-left: 22rpx;"> | |
| 150 | - <view class="u-flex popup-alarm-child"> | |
| 151 | - <view class="home-text-muted">选择日期</view> | |
| 152 | - <view | |
| 153 | - style="width: 623rpx;margin-left: 5rpx;margin-right: 70rpx;margin-top: 35rpx;"> | |
| 154 | - <uni-datetime-picker v-model="range" type="datetimerange" | |
| 155 | - rangeSeparator="至" /> | |
| 156 | - </view> | |
| 157 | - </view> | |
| 158 | - </view> | |
| 159 | - <view style="height: 130rpx;"></view> | |
| 160 | - <view class="u-flex" | |
| 161 | - style="position: fixed;bottom: 10rpx;z-index: 9999;flex-direction: row; margin-top: 128rpx; margin-left: 10rpx"> | |
| 162 | - <view style="width: 300rpx"> | |
| 163 | - <u-button @click="resetData" type="info" shape="circle" text="重置"> | |
| 164 | - </u-button> | |
| 165 | - </view> | |
| 166 | - <view style="width: 300rpx; margin-left: 46rpx"> | |
| 167 | - <u-button @click="queryData" type="primary" shape="circle" text="确认"> | |
| 168 | - </u-button> | |
| 169 | - </view> | |
| 170 | - </view> | |
| 171 | - <view style="height: 90rpx;"></view> | |
| 172 | - </view> | |
| 173 | - </view> | |
| 174 | - </view> | |
| 175 | - </view> | |
| 176 | - </view> | |
| 177 | - </view> | |
| 178 | - </u-popup> | |
| 179 | - <f-tabbar></f-tabbar> | |
| 180 | - </view> | |
| 181 | -</template> | |
| 182 | - | |
| 183 | -<script> | |
| 184 | - import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 185 | - import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 186 | - import { | |
| 187 | - alertStatus, | |
| 188 | - deviceType, | |
| 189 | - alertLevel, | |
| 190 | - timeArea | |
| 191 | - } from './static/data.js'; | |
| 192 | - import api from '@/api/index.js' | |
| 193 | - | |
| 194 | - export default { | |
| 195 | - mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) | |
| 196 | - components: { | |
| 197 | - fTabbar | |
| 198 | - }, | |
| 199 | - data() { | |
| 200 | - return { | |
| 201 | - range: [], | |
| 202 | - alertStatusVal: '', | |
| 203 | - deviceTypeVal: '', | |
| 204 | - alertLevelVal: '', | |
| 205 | - selectTimeVal: '', | |
| 206 | - current1: 0, | |
| 207 | - current2: 0, | |
| 208 | - current3: 0, | |
| 209 | - current4: 0, | |
| 210 | - page: { | |
| 211 | - num: 0, | |
| 212 | - size: 10 | |
| 213 | - }, | |
| 214 | - downOption: { | |
| 215 | - auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 216 | - }, | |
| 217 | - upOption: { | |
| 218 | - auto: false // 不自动加载 | |
| 219 | - }, | |
| 220 | - timeData: { | |
| 221 | - selectTime: [], | |
| 222 | - getTimeGapS: '', | |
| 223 | - getTimeGapE: '' | |
| 224 | - }, | |
| 225 | - show: false, | |
| 226 | - list: [], | |
| 227 | - alertStatus, | |
| 228 | - deviceType, | |
| 229 | - alertLevel, | |
| 230 | - timeArea, | |
| 231 | - ordId: '', | |
| 232 | - detailStatus: false, | |
| 233 | - alertTotal: 0, | |
| 234 | - searchAlarmText: '', | |
| 235 | - startTimeVa: '', | |
| 236 | - endTimeVa: '', | |
| 237 | - startTimeArea: '', | |
| 238 | - endTimeArea: '', | |
| 239 | - type: null | |
| 240 | - }; | |
| 241 | - }, | |
| 242 | - onShow() { | |
| 243 | - this.page.num = 1; | |
| 244 | - if(getApp().getBindNot()){ | |
| 245 | - return | |
| 246 | - } | |
| 247 | - if (this.detailStatus) { | |
| 248 | - this.loadData(1, null, null, null, null, null, null); | |
| 249 | - } | |
| 250 | - if (this.ordId) { | |
| 251 | - this.loadData(1, null, null, null, null, null, this.ordId); | |
| 252 | - } | |
| 253 | - }, | |
| 254 | - onHide() { | |
| 255 | - this.ordId = ''; | |
| 256 | - this.detailStatus = false; | |
| 257 | - this.type = null; | |
| 258 | - }, | |
| 259 | - onLoad(e) { | |
| 260 | - // 隐藏原生的tabbar | |
| 261 | - uni.hideTabBar(); | |
| 262 | - if(getApp().getBindNot()){ | |
| 263 | - return | |
| 264 | - } | |
| 265 | - if (e.type == undefined) { | |
| 266 | - this.loadData(1, null, null, null, null, null, null); | |
| 267 | - } else { | |
| 268 | - let params = JSON.parse(e.type); | |
| 269 | - if (Array.isArray(params)) { | |
| 270 | - this.type = params.join(','); | |
| 271 | - } else { | |
| 272 | - this.type = params; | |
| 273 | - } | |
| 274 | - this.loadData(1, this.type, null, null, null, null, null); | |
| 275 | - } | |
| 276 | - }, | |
| 277 | - watch: { | |
| 278 | - range(newval) { | |
| 279 | - this.timeData.selectTime = this.range; | |
| 280 | - } | |
| 281 | - }, | |
| 282 | - methods: { | |
| 283 | - moveHandle() { | |
| 284 | - return false; | |
| 285 | - }, | |
| 286 | - inputChanged(e) { | |
| 287 | - this.resetData(); | |
| 288 | - this.topBack(); | |
| 289 | - this.searchAlarmText = e; | |
| 290 | - this.page.num = 1; | |
| 291 | - this.loadData(1, null, null, null, null, null, null, e); | |
| 292 | - }, | |
| 293 | - getAlertStatus(e, i) { | |
| 294 | - this.current1 = i; | |
| 295 | - this.alertStatusVal = e.value; | |
| 296 | - }, | |
| 297 | - getTypeStatus(e, i) { | |
| 298 | - this.current2 = i; | |
| 299 | - this.deviceTypeVal = e.value; | |
| 300 | - }, | |
| 301 | - getLevelStatus(e, i) { | |
| 302 | - this.current3 = i; | |
| 303 | - this.alertLevelVal = e.value; | |
| 304 | - }, | |
| 305 | - getTimeStatus(e, i) { | |
| 306 | - this.current4 = i; | |
| 307 | - this.selectTimeVal = e.value; | |
| 308 | - let curTime = new Date(); | |
| 309 | - const formatS = curTime.getTime(); | |
| 310 | - let addMinute = new Date(curTime.setMinutes(curTime.getMinutes() - this.selectTimeVal)); | |
| 311 | - const formatE = addMinute.getTime(); | |
| 312 | - this.timeData.getTimeGapS = i>0?formatS:''; | |
| 313 | - this.timeData.getTimeGapE = i>0?formatE:''; | |
| 314 | - console.log(this.timeData.getTimeGapS,'this.timeData.getTimeGapS',this.timeData.getTimeGapE) | |
| 315 | - }, | |
| 316 | - queryData() { | |
| 317 | - this.topBack(); | |
| 318 | - this.page.num = 1; | |
| 319 | - let date1 = new Date(this.timeData.selectTime[0]); | |
| 320 | - let date2 = new Date(this.timeData.selectTime[1]); | |
| 321 | - if (this.timeData.selectTime.length == 0) { | |
| 322 | - this.startTimeVa = ''; | |
| 323 | - this.endTimeVa = ''; | |
| 324 | - } else { | |
| 325 | - this.startTimeVa = date1.getTime(); | |
| 326 | - this.endTimeVa = date2.getTime(); | |
| 327 | - } | |
| 328 | - if (this.timeData.getTimeGapS == '') { | |
| 329 | - this.startTimeArea = ''; | |
| 330 | - this.endTimeArea = ''; | |
| 331 | - } else { | |
| 332 | - this.startTimeArea = this.timeData.getTimeGapE; | |
| 333 | - this.endTimeArea = this.timeData.getTimeGapS; | |
| 334 | - } | |
| 335 | - this.loadData( | |
| 336 | - 1, | |
| 337 | - this.alertStatusVal, | |
| 338 | - this.startTimeVa ? this.startTimeVa : this.startTimeArea, | |
| 339 | - this.endTimeVa ? this.endTimeVa : this.endTimeArea, | |
| 340 | - this.alertLevelVal, | |
| 341 | - this.deviceTypeVal | |
| 342 | - ); | |
| 343 | - this.show = false; | |
| 344 | - }, | |
| 345 | - resetData() { | |
| 346 | - this.current1 = 0; | |
| 347 | - this.alertStatusVal = ''; | |
| 348 | - this.current2 = 0; | |
| 349 | - this.deviceTypeVal = ''; | |
| 350 | - this.current3 = 0; | |
| 351 | - this.alertLevelVal = ''; | |
| 352 | - this.current4 = 0; | |
| 353 | - this.selectTimeVal = ''; | |
| 354 | - this.timeData.selectTime = []; | |
| 355 | - this.timeData.getTimeGapS = ''; | |
| 356 | - this.timeData.getTimeGapE = ''; | |
| 357 | - this.range = []; | |
| 358 | - this.searchAlarmText = ''; | |
| 359 | - this.startTimeVa = ''; | |
| 360 | - this.endTimeVa = ''; | |
| 361 | - this.startTimeArea = ''; | |
| 362 | - this.endTimeArea = ''; | |
| 363 | - this.ordId = ''; | |
| 364 | - this.type = null; | |
| 365 | - }, | |
| 366 | - bindImageUrl(e) { | |
| 367 | - switch (e) { | |
| 368 | - case 'CRITICAL': | |
| 369 | - return '../../static/danger.png'; | |
| 370 | - break; | |
| 371 | - case 'MAJOR': | |
| 372 | - return '../../static/major.png'; | |
| 373 | - break; | |
| 374 | - case 'MINOR': | |
| 375 | - return '../../static/secondary.png'; | |
| 376 | - break; | |
| 377 | - case 'WARNING': | |
| 378 | - return '../../static/danger.png'; | |
| 379 | - break; | |
| 380 | - case 'INDETERMINATE': | |
| 381 | - return '../../static/noshue.png'; | |
| 382 | - break; | |
| 383 | - default: | |
| 384 | - return ''; | |
| 385 | - break; | |
| 386 | - } | |
| 387 | - }, | |
| 388 | - //筛选数据让它回到顶部 | |
| 389 | - topBack() { | |
| 390 | - uni.pageScrollTo({ | |
| 391 | - scrollTop: 0, // 滚动到页面的目标位置 这个是滚动到顶部, 0 | |
| 392 | - duration: 10 // 滚动动画的时长 | |
| 393 | - }); | |
| 394 | - }, | |
| 395 | - /*下拉刷新的回调 */ | |
| 396 | - downCallback() { | |
| 397 | - //联网加载数据 | |
| 398 | - this.list.length = 0; | |
| 399 | - this.page.num = 1; | |
| 400 | - this.loadData(this.page.num, null, null, null, null, null, null, null); | |
| 401 | - this.resetData(); | |
| 402 | - }, | |
| 403 | - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 404 | - upCallback() { | |
| 405 | - if ( | |
| 406 | - this.type != null || | |
| 407 | - this.alertStatusVal != '' || | |
| 408 | - this.searchAlarmText != '' || | |
| 409 | - this.deviceTypeVal != '' || | |
| 410 | - this.alertLevelVal != '' || | |
| 411 | - this.startTimeVa != '' || | |
| 412 | - this.startTimeArea != '' || | |
| 413 | - this.ordId != '' | |
| 414 | - ) { | |
| 415 | - //联网加载数据 | |
| 416 | - this.page.num += 1; | |
| 417 | - this.loadData( | |
| 418 | - this.page.num, | |
| 419 | - this.alertStatusVal ? this.alertStatusVal : this.type, | |
| 420 | - this.startTimeVa, | |
| 421 | - this.endTimeVa, | |
| 422 | - this.alertLevelVal, | |
| 423 | - this.deviceTypeVal, | |
| 424 | - this.ordId, | |
| 425 | - this.searchAlarmText | |
| 426 | - ); | |
| 427 | - } else { | |
| 428 | - //联网加载数据 | |
| 429 | - this.page.num += 1; | |
| 430 | - this.loadData(this.page.num); | |
| 431 | - } | |
| 432 | - }, | |
| 433 | - async loadData(pageNo, statusV, startTimeV, endTimeV, severityV, deviceTypeV, organizationV, alarmName) { | |
| 434 | - let that = this; | |
| 435 | - let httpData = { | |
| 436 | - page: pageNo, | |
| 437 | - pageSize: 10, | |
| 438 | - status: statusV, | |
| 439 | - startTime: startTimeV, | |
| 440 | - endTime: endTimeV, | |
| 441 | - severity: severityV, | |
| 442 | - deviceType: deviceTypeV, | |
| 443 | - organizationId: organizationV, | |
| 444 | - deviceName: alarmName | |
| 445 | - }; | |
| 446 | - if (statusV == '') { | |
| 447 | - delete httpData.status; | |
| 448 | - } | |
| 449 | - if (severityV == '') { | |
| 450 | - delete httpData.severity; | |
| 451 | - } | |
| 452 | - const res = await api.alarmApi.getAlarmApi({ | |
| 453 | - params: httpData, | |
| 454 | - custom: { | |
| 455 | - load: false | |
| 456 | - } | |
| 457 | - }) | |
| 458 | - if (res) { | |
| 459 | - uni.stopPullDownRefresh(); | |
| 460 | - that.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数) | |
| 461 | - that.alertTotal = res.total; | |
| 462 | - if (pageNo == 1) { | |
| 463 | - that.list = res.items; | |
| 464 | - } else { | |
| 465 | - that.list = that.list.concat(res.items); | |
| 466 | - } | |
| 467 | - } | |
| 468 | - }, | |
| 469 | - openOrg() { | |
| 470 | - uni.navigateTo({ | |
| 471 | - url: './org/org' | |
| 472 | - }); | |
| 473 | - }, | |
| 474 | - close() { | |
| 475 | - this.show = false; | |
| 476 | - }, | |
| 477 | - openSearchDialog() { | |
| 478 | - this.show = true; | |
| 479 | - this.resetData(); | |
| 480 | - }, | |
| 481 | - //跳转告警详情 | |
| 482 | - openAlertDetail(e) { | |
| 483 | - let obj = { | |
| 484 | - id: e.id, | |
| 485 | - deviceName: e.deviceName, | |
| 486 | - severity: e.severity, | |
| 487 | - organizationName: e.organizationName, | |
| 488 | - details: e.details, | |
| 489 | - createdTime: e.createdTime, | |
| 490 | - status: e.status, | |
| 491 | - type: e.type | |
| 492 | - }; | |
| 493 | - uni.navigateTo({ | |
| 494 | - url: '/alarmSubPage/alarmDetailPage/alarmDetail?data=' + JSON.stringify(obj) | |
| 495 | - }); | |
| 496 | - }, | |
| 497 | - formatDetailText(e) { | |
| 498 | - //去除字符串双引号 | |
| 499 | - const jsonStr = JSON.stringify(e); | |
| 500 | - const str = jsonStr.substring(1, jsonStr.length - 1); | |
| 501 | - const newStr = str.replace(/\"/g, ''); | |
| 502 | - return newStr; | |
| 503 | - } | |
| 504 | - } | |
| 505 | - }; | |
| 506 | -</script> | |
| 507 | - | |
| 508 | -<style lang="scss" scoped> | |
| 509 | - @import './static/alarm.scss'; | |
| 510 | - | |
| 511 | - /deep/ .u-button--primary { | |
| 512 | - background-color: #377dff !important; | |
| 513 | - border-color: #377dff !important; | |
| 514 | - } | |
| 515 | - | |
| 516 | - /deep/ .u-button--info { | |
| 517 | - background-color: #e3e3e5 !important; | |
| 518 | - border-color: #e3e3e5 !important; | |
| 519 | - } | |
| 520 | - | |
| 521 | - /deep/ .u-cell__right-icon-wrap { | |
| 522 | - margin-top: -55rpx !important; | |
| 523 | - } | |
| 524 | - | |
| 525 | - /deep/ .uni-calendar--fixed { | |
| 526 | - bottom: 172rpx !important; | |
| 527 | - } | |
| 528 | - | |
| 529 | - .pop-no-scroll { | |
| 530 | - overflow: hidden; | |
| 531 | - position: fixed; | |
| 532 | - height: 100%; | |
| 533 | - width: 100%; | |
| 534 | - } | |
| 535 | - | |
| 536 | - .device-top { | |
| 537 | - padding: 10rpx 30rpx; | |
| 538 | - background-color: #fff; | |
| 539 | - | |
| 540 | - .search { | |
| 541 | - display: flex; | |
| 542 | - justify-content: space-between; | |
| 543 | - padding-bottom: 10rpx; | |
| 544 | - | |
| 545 | - .search-left { | |
| 546 | - width: 580rpx; | |
| 547 | - background-color: #f8f9fa; | |
| 548 | - border-radius: 200rpx; | |
| 549 | - } | |
| 550 | - | |
| 551 | - .search-right { | |
| 552 | - display: flex; | |
| 553 | - align-items: center; | |
| 554 | - | |
| 555 | - text { | |
| 556 | - color: #333; | |
| 557 | - font-size: 14px; | |
| 558 | - } | |
| 559 | - | |
| 560 | - image { | |
| 561 | - width: 40rpx; | |
| 562 | - height: 40rpx; | |
| 563 | - } | |
| 564 | - } | |
| 565 | - } | |
| 566 | - } | |
| 567 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="alarm-page" :class="pageDisableScroll"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <!-- 告警头部 --> | |
| 6 | + <header-search @openOrg="openOrg" @openSearchDialog="openSearchDialog" :total="alarmTotal" | |
| 7 | + :totalText="totalText"> | |
| 8 | + <!-- 不能写在封装组件里传placeholder,mp-wenxin端编译要报错 --> | |
| 9 | + <u--input prefixIcon="search" placeholder="请输入告警设备" shape="circle" @change="inputChanged"> | |
| 10 | + </u--input> | |
| 11 | + </header-search> | |
| 12 | + <!-- 告警分页 --> | |
| 13 | + <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 14 | + @up="upCallback"> | |
| 15 | + <alarm-item :list="list" @openAlertDetail="openAlertDetail"></alarm-item> | |
| 16 | + <mescroll-empty v-if="!list.length" /> | |
| 17 | + </mescroll-body> | |
| 18 | + <view style="height: 20rpx"></view> | |
| 19 | + <!-- 告警筛选--> | |
| 20 | + <alarm-popup ref="alarmPopupRef" :show="show" @close="close" @queryCondition="getQueryCondition"></alarm-popup> | |
| 21 | + <f-tabbar></f-tabbar> | |
| 22 | + </view> | |
| 23 | +</template> | |
| 24 | + | |
| 25 | +<script> | |
| 26 | + import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 27 | + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 28 | + import api from '@/api/index.js' | |
| 29 | + import alarmItem from './components/alarm-item.vue' | |
| 30 | + import alarmPopup from './components/alarm-popup.vue' | |
| 31 | + import { | |
| 32 | + usePageScrollTo, | |
| 33 | + useNavigateTo | |
| 34 | + } from '@/plugins/utils.js' | |
| 35 | + | |
| 36 | + | |
| 37 | + export default { | |
| 38 | + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) | |
| 39 | + components: { | |
| 40 | + fTabbar, | |
| 41 | + alarmItem, | |
| 42 | + alarmPopup | |
| 43 | + }, | |
| 44 | + data() { | |
| 45 | + return { | |
| 46 | + totalText: '告警数:', | |
| 47 | + page: { | |
| 48 | + num: 0, | |
| 49 | + size: 10 | |
| 50 | + }, | |
| 51 | + downOption: { | |
| 52 | + auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 53 | + }, | |
| 54 | + upOption: { | |
| 55 | + auto: false // 不自动加载 | |
| 56 | + }, | |
| 57 | + show: false, | |
| 58 | + list: [], | |
| 59 | + alarmTotal: 0, | |
| 60 | + queryCondition: { | |
| 61 | + searchAlarmText: '', | |
| 62 | + }, | |
| 63 | + conditions: {}, | |
| 64 | + ordId: '', | |
| 65 | + }; | |
| 66 | + }, | |
| 67 | + onShow() { | |
| 68 | + if (getApp().getBindNot()) { | |
| 69 | + return | |
| 70 | + } | |
| 71 | + if (this.ordId) { | |
| 72 | + this.loadData(1, { | |
| 73 | + organizationId: this.ordId | |
| 74 | + }); | |
| 75 | + this.conditions = { | |
| 76 | + organizationId: this.ordId | |
| 77 | + } | |
| 78 | + } | |
| 79 | + }, | |
| 80 | + onHide() { | |
| 81 | + this.ordId = '' | |
| 82 | + }, | |
| 83 | + onLoad(e) { | |
| 84 | + if (!e.type) { | |
| 85 | + this.loadData(1); | |
| 86 | + } else { | |
| 87 | + let params = JSON.parse(e.type); | |
| 88 | + let status = null | |
| 89 | + if (Array.isArray(params)) { | |
| 90 | + status = params.join(','); | |
| 91 | + } else { | |
| 92 | + status = params; | |
| 93 | + } | |
| 94 | + this.conditions = { | |
| 95 | + status | |
| 96 | + } | |
| 97 | + this.loadData(1, { | |
| 98 | + status | |
| 99 | + }); | |
| 100 | + } | |
| 101 | + // 隐藏原生的tabbar | |
| 102 | + uni.hideTabBar(); | |
| 103 | + if (getApp().getBindNot()) { | |
| 104 | + return | |
| 105 | + } | |
| 106 | + }, | |
| 107 | + computed: { | |
| 108 | + pageDisableScroll() { | |
| 109 | + return this.show ? 'pop-no-scroll' : '' | |
| 110 | + } | |
| 111 | + }, | |
| 112 | + methods: { | |
| 113 | + inputChanged(e) { | |
| 114 | + this.resetQuery(); | |
| 115 | + this.topBack(); | |
| 116 | + this.queryCondition.searchAlarmText = e; | |
| 117 | + this.page.num = 1; | |
| 118 | + this.conditions = { | |
| 119 | + deviceName: e | |
| 120 | + } | |
| 121 | + this.loadData(1, { | |
| 122 | + deviceName: e | |
| 123 | + }); | |
| 124 | + }, | |
| 125 | + getQueryCondition(value) { | |
| 126 | + this.loadData(1, value); | |
| 127 | + this.conditions = value | |
| 128 | + this.close() | |
| 129 | + }, | |
| 130 | + resetQuery() { | |
| 131 | + this.queryCondition.searchAlarmText = ''; | |
| 132 | + this.page.num = 1; | |
| 133 | + this.$nextTick(() => { | |
| 134 | + this.$refs.alarmPopupRef.resetQuery() | |
| 135 | + }) | |
| 136 | + this.conditions = {} | |
| 137 | + }, | |
| 138 | + topBack() { | |
| 139 | + usePageScrollTo(0, 10) | |
| 140 | + }, | |
| 141 | + //下拉刷新 | |
| 142 | + downCallback() { | |
| 143 | + this.list.length = 0; | |
| 144 | + this.page.num = 1; | |
| 145 | + this.resetQuery(); | |
| 146 | + this.loadData(this.page.num); | |
| 147 | + }, | |
| 148 | + //上拉加载 | |
| 149 | + upCallback() { | |
| 150 | + const condition = Object.values(this.conditions) | |
| 151 | + if (condition.length === 0) { | |
| 152 | + this.page.num += 1; | |
| 153 | + this.loadData(this.page.num); | |
| 154 | + } else if (condition.filter(Boolean).length > 0) { | |
| 155 | + this.page.num += 1; | |
| 156 | + this.loadData(this.page.num, this.conditions); | |
| 157 | + } else { | |
| 158 | + this.page.num += 1; | |
| 159 | + this.loadData(this.page.num); | |
| 160 | + } | |
| 161 | + }, | |
| 162 | + async loadData(page, param) { | |
| 163 | + let that = this; | |
| 164 | + let params = { | |
| 165 | + page, | |
| 166 | + pageSize: 10, | |
| 167 | + ...param | |
| 168 | + }; | |
| 169 | + const res = await api.alarmApi.getAlarmApi({ | |
| 170 | + params, | |
| 171 | + custom: { | |
| 172 | + load: false | |
| 173 | + } | |
| 174 | + }) | |
| 175 | + if (!res) return | |
| 176 | + uni.stopPullDownRefresh(); | |
| 177 | + that.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数) | |
| 178 | + that.alarmTotal = res.total; | |
| 179 | + if (page == 1) { | |
| 180 | + that.list = res.items; | |
| 181 | + } else { | |
| 182 | + that.list = that.list.concat(res.items); | |
| 183 | + } | |
| 184 | + }, | |
| 185 | + close() { | |
| 186 | + this.show = false; | |
| 187 | + }, | |
| 188 | + openSearchDialog() { | |
| 189 | + this.show = true; | |
| 190 | + this.$nextTick(() => { | |
| 191 | + this.resetQuery(); | |
| 192 | + }) | |
| 193 | + }, | |
| 194 | + openOrg() { | |
| 195 | + useNavigateTo('/pages/organization/organization') | |
| 196 | + }, | |
| 197 | + //跳转告警详情 | |
| 198 | + openAlertDetail(e) { | |
| 199 | + useNavigateTo('/alarm-subpackage/alarm-detail/alarm-detail?data=', e) | |
| 200 | + }, | |
| 201 | + } | |
| 202 | + }; | |
| 203 | +</script> | |
| 204 | + | |
| 205 | +<style lang="scss" scoped> | |
| 206 | + @import './static/alarm.scss'; | |
| 207 | + | |
| 208 | + /deep/ .u-button--primary { | |
| 209 | + background-color: #377dff !important; | |
| 210 | + border-color: #377dff !important; | |
| 211 | + } | |
| 212 | + | |
| 213 | + /deep/ .u-button--info { | |
| 214 | + background-color: #e3e3e5 !important; | |
| 215 | + border-color: #e3e3e5 !important; | |
| 216 | + } | |
| 217 | + | |
| 218 | + /deep/ .u-cell__right-icon-wrap { | |
| 219 | + margin-top: -55rpx !important; | |
| 220 | + } | |
| 221 | + | |
| 222 | + /deep/ .uni-calendar--fixed { | |
| 223 | + bottom: 172rpx !important; | |
| 224 | + } | |
| 225 | + | |
| 226 | + .pop-no-scroll { | |
| 227 | + overflow: hidden; | |
| 228 | + position: fixed; | |
| 229 | + height: 100%; | |
| 230 | + width: 100%; | |
| 231 | + } | |
| 232 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/alarm/components/alarm-item.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="alarm-list"> | |
| 3 | + <view @click="$emit('openAlertDetail',item)" class="list-item" v-for="(item, index) in list" :key="index"> | |
| 4 | + <view class="u-flex item"> | |
| 5 | + <view class="item-text text-clip"> | |
| 6 | + <text class="text-bold">{{ item.deviceName == null ? '暂无数据' : item.deviceName }}</text> | |
| 7 | + </view> | |
| 8 | + <view class="item-text text-clip"> | |
| 9 | + <text class="text-muted">{{ item.details == null ? '暂无数据' : formatDetailText(item.details) }}</text> | |
| 10 | + </view> | |
| 11 | + <view class="item-text"> | |
| 12 | + <text class="text-muted"> | |
| 13 | + 告警状态:{{item.status | setAlarmStatus(alarmStatus)}} | |
| 14 | + </text> | |
| 15 | + </view> | |
| 16 | + <view class="item-text"> | |
| 17 | + <text class="text-secondary">{{ item.createdTime }}</text> | |
| 18 | + </view> | |
| 19 | + </view> | |
| 20 | + <view class="item"> | |
| 21 | + <view class="u-flex item-right"> | |
| 22 | + <image class="right-image" :src="bindImageUrl(item.severity)"></image> | |
| 23 | + <view class="right-text"> | |
| 24 | + <text class="text-no-color" :style="[setAlarmSeverityColor(item.severity,alarmSeverity)]"> | |
| 25 | + {{item.severity | setAlarmSeverity(alarmSeverity)}} | |
| 26 | + </text> | |
| 27 | + </view> | |
| 28 | + </view> | |
| 29 | + </view> | |
| 30 | + </view> | |
| 31 | + </view> | |
| 32 | +</template> | |
| 33 | + | |
| 34 | +<script> | |
| 35 | + import { | |
| 36 | + alarmSeverity, | |
| 37 | + alarmStatus | |
| 38 | + } from '../config/data.js'; | |
| 39 | + | |
| 40 | + export default { | |
| 41 | + props: { | |
| 42 | + list: { | |
| 43 | + type: Array, | |
| 44 | + default: [] | |
| 45 | + } | |
| 46 | + }, | |
| 47 | + data() { | |
| 48 | + return { | |
| 49 | + alarmSeverity, | |
| 50 | + alarmStatus | |
| 51 | + } | |
| 52 | + }, | |
| 53 | + filters: { | |
| 54 | + setAlarmStatus(value, list) { | |
| 55 | + return list.find(item => item.value === value).label | |
| 56 | + }, | |
| 57 | + setAlarmSeverity(value, list) { | |
| 58 | + return list.find(item => item.value === value).label | |
| 59 | + } | |
| 60 | + }, | |
| 61 | + methods: { | |
| 62 | + setAlarmSeverityColor(value, list) { | |
| 63 | + return { | |
| 64 | + color: list.find(item => item.value === value).color | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + bindImageUrl(e) { | |
| 68 | + return this.alarmSeverity.find(item => item.value === e).icon | |
| 69 | + }, | |
| 70 | + formatDetailText(e) { | |
| 71 | + const keys = Object.keys(e) | |
| 72 | + if(!keys) return | |
| 73 | + const values = keys.reduce((acc, curr) => { | |
| 74 | + acc.push(`${!e[curr].key?'暂无数据':e[curr].key}:${!e[curr].realValue?'暂无数据':e[curr].realValue}`) | |
| 75 | + return acc | |
| 76 | + }, []) | |
| 77 | + return values.join(',') | |
| 78 | + } | |
| 79 | + } | |
| 80 | + } | |
| 81 | +</script> | |
| 82 | + | |
| 83 | +<style lang="scss" scoped> | |
| 84 | + .alarm-list { | |
| 85 | + display: flex; | |
| 86 | + flex-direction: column; | |
| 87 | + padding-left: 18rpx; | |
| 88 | + justify-content: flex-start; | |
| 89 | + | |
| 90 | + .list-item { | |
| 91 | + width: 713rpx; | |
| 92 | + height: 233rpx; | |
| 93 | + background-color: #fff; | |
| 94 | + margin-top: 24rpx; | |
| 95 | + display: flex; | |
| 96 | + flex-direction: row; | |
| 97 | + border-radius: 10px; | |
| 98 | + justify-content: space-between; | |
| 99 | + | |
| 100 | + .item { | |
| 101 | + justify-content: flex-start; | |
| 102 | + flex-direction: column; | |
| 103 | + align-items: center; | |
| 104 | + height: 211rpx; | |
| 105 | + margin-top: 8rpx; | |
| 106 | + margin-left: 37rpx; | |
| 107 | + | |
| 108 | + .item-text { | |
| 109 | + width: 400rpx; | |
| 110 | + text-align: left; | |
| 111 | + margin-top: 13rpx; | |
| 112 | + line-height: 40rpx; | |
| 113 | + | |
| 114 | + .text { | |
| 115 | + color: #666666; | |
| 116 | + font-size: 15px; | |
| 117 | + } | |
| 118 | + | |
| 119 | + .text-three { | |
| 120 | + color: #333333; | |
| 121 | + font-size: 15px; | |
| 122 | + } | |
| 123 | + | |
| 124 | + .text-nine { | |
| 125 | + color: #999999; | |
| 126 | + font-size: 15px; | |
| 127 | + } | |
| 128 | + } | |
| 129 | + | |
| 130 | + .item-right { | |
| 131 | + flex-direction: row; | |
| 132 | + margin-top: -3rpx; | |
| 133 | + margin-right: 25rpx; | |
| 134 | + | |
| 135 | + .right-image { | |
| 136 | + width: 30rpx; | |
| 137 | + height: 30rpx; | |
| 138 | + margin-top: 20rpx; | |
| 139 | + margin-right: 5rpx; | |
| 140 | + } | |
| 141 | + | |
| 142 | + .right-text { | |
| 143 | + color: #333333; | |
| 144 | + font-size: 13px; | |
| 145 | + margin-left: 5rpx; | |
| 146 | + margin-top: 20rpx; | |
| 147 | + } | |
| 148 | + } | |
| 149 | + } | |
| 150 | + } | |
| 151 | + } | |
| 152 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/alarm/components/alarm-popup.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <u-popup @close="$emit('close')" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom"> | |
| 3 | + <view class="popup-page"> | |
| 4 | + <view class="popup-text"><text class="text">告警筛选</text></view> | |
| 5 | + <view class="popup-alarm-page u-flex"> | |
| 6 | + <view> | |
| 7 | + <query-item ref="queryItemAlarmStatusRef" :leftText="leftAlarmStatusText" :queryStatus="alertStatus" | |
| 8 | + @currentClick="getAlarmStatus"></query-item> | |
| 9 | + <query-item ref="queryDeviceTypeStatusRef" :leftText="leftDeviceTypeText" :queryStatus="deviceType" | |
| 10 | + @currentClick="getDeviceType"></query-item> | |
| 11 | + <query-item ref="queryItemAlarmLevelRef" :leftText="leftAlarmLevelText" :queryStatus="alertLevel" | |
| 12 | + @currentClick="getAlarmLevel"></query-item> | |
| 13 | + <query-item ref="queryItemSelectTimeRef" :leftText="leftSelectTimeText" :queryStatus="timeArea" | |
| 14 | + @currentClick="getSelectTime"></query-item> | |
| 15 | + <view class="select-date"> | |
| 16 | + <view class="home-text-muted">选择日期</view> | |
| 17 | + <view class="datetime-picker"> | |
| 18 | + <uni-datetime-picker return-type="timestamp" v-model="range" type="datetimerange" | |
| 19 | + rangeSeparator="至" /> | |
| 20 | + </view> | |
| 21 | + </view> | |
| 22 | + <view class="h-30"></view> | |
| 23 | + <view class="u-flex bottom-button"> | |
| 24 | + <view class="button-item"> | |
| 25 | + <u-button @click="resetQuery" type="info" shape="circle" text="重置"> | |
| 26 | + </u-button> | |
| 27 | + </view> | |
| 28 | + <view class="button-item" style="margin-left: 46rpx"> | |
| 29 | + <u-button @click="confirmQuery" type="primary" shape="circle" text="确认"> | |
| 30 | + </u-button> | |
| 31 | + </view> | |
| 32 | + </view> | |
| 33 | + <view style="height: 90rpx;"></view> | |
| 34 | + </view> | |
| 35 | + </view> | |
| 36 | + </view> | |
| 37 | + </u-popup> | |
| 38 | +</template> | |
| 39 | + | |
| 40 | +<script> | |
| 41 | + import { | |
| 42 | + alertStatus, | |
| 43 | + deviceType, | |
| 44 | + alertLevel, | |
| 45 | + timeArea | |
| 46 | + } from '../config/data.js'; | |
| 47 | + import queryItem from './query-item.vue' | |
| 48 | + | |
| 49 | + export default { | |
| 50 | + components: { | |
| 51 | + queryItem | |
| 52 | + }, | |
| 53 | + props: { | |
| 54 | + show: Boolean | |
| 55 | + }, | |
| 56 | + data() { | |
| 57 | + return { | |
| 58 | + totalText: '告警数:', | |
| 59 | + leftAlarmStatusText: '告警状态', | |
| 60 | + leftDeviceTypeText: '设备类型', | |
| 61 | + leftAlarmLevelText: '告警等级', | |
| 62 | + leftSelectTimeText: '选择时间', | |
| 63 | + range: [], | |
| 64 | + alertStatus, | |
| 65 | + deviceType, | |
| 66 | + alertLevel, | |
| 67 | + timeArea, | |
| 68 | + queryCondition: { | |
| 69 | + status: '', | |
| 70 | + deviceType: '', | |
| 71 | + severity: '', | |
| 72 | + startTime: 0, | |
| 73 | + endTime: 0, | |
| 74 | + }, | |
| 75 | + | |
| 76 | + }; | |
| 77 | + }, | |
| 78 | + computed: { | |
| 79 | + hignLightColor() { | |
| 80 | + return `background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)'` | |
| 81 | + }, | |
| 82 | + unHighlightColor() { | |
| 83 | + return `background: '#F6F6F6'` | |
| 84 | + } | |
| 85 | + }, | |
| 86 | + methods: { | |
| 87 | + getAlarmStatus(e) { | |
| 88 | + this.queryCondition.status = e.value; | |
| 89 | + }, | |
| 90 | + getDeviceType(e) { | |
| 91 | + this.queryCondition.deviceType = e.value; | |
| 92 | + }, | |
| 93 | + getAlarmLevel(e) { | |
| 94 | + this.queryCondition.severity = e.value; | |
| 95 | + }, | |
| 96 | + getSelectTime(e, i) { | |
| 97 | + const curTime = new Date(); | |
| 98 | + const getStartTs = curTime.getTime(); | |
| 99 | + const calcDate = new Date(curTime.setMinutes(curTime.getMinutes() - e.value)); | |
| 100 | + const getEndTs = calcDate.getTime(); | |
| 101 | + this.queryCondition.startTime = getEndTs | |
| 102 | + this.queryCondition.endTime = getStartTs | |
| 103 | + }, | |
| 104 | + confirmQuery() { | |
| 105 | + if (Array.isArray(this.range) && this.range.length > 0) { | |
| 106 | + this.queryCondition.startTime = this.range[0] | |
| 107 | + this.queryCondition.endTime = this.range[1] | |
| 108 | + } | |
| 109 | + this.$emit('queryCondition', this.queryCondition) | |
| 110 | + }, | |
| 111 | + resetQuery() { | |
| 112 | + for (let i in this.queryCondition) Reflect.set(this.queryCondition, i, '') | |
| 113 | + this.range = [] | |
| 114 | + this.$nextTick(() => { | |
| 115 | + this.$refs.queryItemAlarmStatusRef.reset() | |
| 116 | + this.$refs.queryDeviceTypeStatusRef.reset() | |
| 117 | + this.$refs.queryItemAlarmLevelRef.reset() | |
| 118 | + this.$refs.queryItemSelectTimeRef.reset() | |
| 119 | + }) | |
| 120 | + }, | |
| 121 | + } | |
| 122 | + }; | |
| 123 | +</script> | |
| 124 | + | |
| 125 | + | |
| 126 | +<style lang="scss" scoped> | |
| 127 | + .popup-page { | |
| 128 | + height: 1100rpx; | |
| 129 | + background: #ffffff; | |
| 130 | + border-radius: 20rpx; | |
| 131 | + overflow-y: scroll; | |
| 132 | + overflow-x: hidden; | |
| 133 | + | |
| 134 | + .popup-text { | |
| 135 | + text-align: center; | |
| 136 | + position: relative; | |
| 137 | + top: 68rpx; | |
| 138 | + margin-top: -40rpx; | |
| 139 | + | |
| 140 | + .text { | |
| 141 | + font-size: 16px; | |
| 142 | + color: #333333; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + | |
| 146 | + .popup-alarm-page { | |
| 147 | + margin-top: 97rpx; | |
| 148 | + margin-left: 98rpx; | |
| 149 | + flex-direction: column; | |
| 150 | + justify-content: space-between; | |
| 151 | + | |
| 152 | + .select-date { | |
| 153 | + display: flex; | |
| 154 | + flex-direction: column; | |
| 155 | + justify-content: space-between; | |
| 156 | + } | |
| 157 | + | |
| 158 | + .datetime-picker { | |
| 159 | + width: 640rpx; | |
| 160 | + margin-left: 5rpx; | |
| 161 | + margin-right: 70rpx; | |
| 162 | + margin-top: 35rpx; | |
| 163 | + } | |
| 164 | + | |
| 165 | + .bottom-button { | |
| 166 | + position: fixed; | |
| 167 | + bottom: 10rpx; | |
| 168 | + z-index: 9999; | |
| 169 | + flex-direction: row; | |
| 170 | + margin-top: 128rpx; | |
| 171 | + margin-left: 10rpx; | |
| 172 | + | |
| 173 | + .button-item { | |
| 174 | + width: 300rpx | |
| 175 | + } | |
| 176 | + } | |
| 177 | + } | |
| 178 | + } | |
| 179 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/alarm/components/query-item.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view> | |
| 3 | + <view class="popup-alarm-text"><text class="text">{{leftText}}</text></view> | |
| 4 | + <view class="u-flex popup-alarm-child"> | |
| 5 | + <view v-for="(item, index) in queryStatus" :key="index" class="alarm-text" @click="currentClick(item,index)" | |
| 6 | + :style="[index == currentIndex ? { hignLightColor } : { unHighlightColor }]"> | |
| 7 | + <text :class="[index == currentIndex ? 'select-text' : 'un-select-text']" | |
| 8 | + class="text">{{ item.name }}</text> | |
| 9 | + </view> | |
| 10 | + </view> | |
| 11 | + <view style="height:180rpx"></view> | |
| 12 | + </view> | |
| 13 | +</template> | |
| 14 | + | |
| 15 | +<script> | |
| 16 | + export default { | |
| 17 | + props: { | |
| 18 | + leftText: String, | |
| 19 | + queryStatus: Array | |
| 20 | + }, | |
| 21 | + data() { | |
| 22 | + return { | |
| 23 | + currentIndex: 0, | |
| 24 | + } | |
| 25 | + }, | |
| 26 | + computed: { | |
| 27 | + hignLightColor() { | |
| 28 | + return `background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)'` | |
| 29 | + }, | |
| 30 | + unHighlightColor() { | |
| 31 | + return `background: '#F6F6F6'` | |
| 32 | + } | |
| 33 | + }, | |
| 34 | + methods: { | |
| 35 | + currentClick(item, index) { | |
| 36 | + this.currentIndex = index | |
| 37 | + this.$emit('currentClick', item, index) | |
| 38 | + }, | |
| 39 | + reset() { | |
| 40 | + this.currentIndex = 0 | |
| 41 | + } | |
| 42 | + } | |
| 43 | + } | |
| 44 | +</script> | |
| 45 | + | |
| 46 | +<style lang="scss" scoped> | |
| 47 | + .popup-alarm-text { | |
| 48 | + width: 750rpx; | |
| 49 | + margin-left: 14rpx; | |
| 50 | + | |
| 51 | + .text { | |
| 52 | + color: #333333; | |
| 53 | + font-size: 14px; | |
| 54 | + } | |
| 55 | + } | |
| 56 | + | |
| 57 | + .popup-alarm-child { | |
| 58 | + margin-top: 15rpx; | |
| 59 | + width: 750rpx; | |
| 60 | + height: 60rpx; | |
| 61 | + flex-wrap: wrap; | |
| 62 | + margin-left: -10rpx; | |
| 63 | + | |
| 64 | + .alarm-text { | |
| 65 | + margin: 25rpx; | |
| 66 | + line-height: 50rpx; | |
| 67 | + text-align: center; | |
| 68 | + width: 180rpx; | |
| 69 | + height: 60rpx; | |
| 70 | + background-color: #f6f6f6; | |
| 71 | + border-radius: 32px; | |
| 72 | + | |
| 73 | + .text { | |
| 74 | + color: #333333; | |
| 75 | + font-size: 13px; | |
| 76 | + } | |
| 77 | + } | |
| 78 | + } | |
| 79 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/alarm/config/data.js
renamed from
pages/alarm/static/data.js
| ... | ... | @@ -72,7 +72,7 @@ const alertLevel = [{ |
| 72 | 72 | }, |
| 73 | 73 | { |
| 74 | 74 | index: 2, |
| 75 | - name: '危险', | |
| 75 | + name: '紧急', | |
| 76 | 76 | value: 'CRITICAL', |
| 77 | 77 | bgColor: '#F6F6F6', |
| 78 | 78 | textColor: '#F6F6F6' |
| ... | ... | @@ -143,9 +143,141 @@ const timeArea = [{ |
| 143 | 143 | textColor: '#F6F6F6' |
| 144 | 144 | } |
| 145 | 145 | ] |
| 146 | + | |
| 147 | +const alarmSeverity = [{ | |
| 148 | + label: '紧急', | |
| 149 | + value: 'CRITICAL', | |
| 150 | + color: '#DE4437', | |
| 151 | + icon: '/static/danger.png', | |
| 152 | + }, | |
| 153 | + { | |
| 154 | + label: '重要', | |
| 155 | + value: 'MAJOR', | |
| 156 | + color: '#DE7337', | |
| 157 | + icon: '/static/major.png', | |
| 158 | + }, | |
| 159 | + { | |
| 160 | + label: '次要', | |
| 161 | + value: 'MINOR', | |
| 162 | + color: '#FFC107', | |
| 163 | + icon: '/static/secondary.png', | |
| 164 | + }, | |
| 165 | + { | |
| 166 | + label: '警告', | |
| 167 | + value: 'WARNING', | |
| 168 | + color: '#DE4437', | |
| 169 | + icon: '/static/danger.png', | |
| 170 | + }, | |
| 171 | + { | |
| 172 | + label: '不确定', | |
| 173 | + value: 'INDETERMINATE', | |
| 174 | + color: '#00C9A7', | |
| 175 | + icon: '/static/noshue.png', | |
| 176 | + }, | |
| 177 | +] | |
| 178 | + | |
| 179 | +const alarmStatus = [{ | |
| 180 | + label: '清除未确认', | |
| 181 | + value: 'CLEARED_UNACK' | |
| 182 | + }, | |
| 183 | + { | |
| 184 | + label: '激活未确认', | |
| 185 | + value: 'ACTIVE_UNACK' | |
| 186 | + }, | |
| 187 | + { | |
| 188 | + label: '清除已确认', | |
| 189 | + value: 'CLEARED_ACK' | |
| 190 | + }, | |
| 191 | + { | |
| 192 | + label: '激活已确认', | |
| 193 | + value: 'ACTIVE_ACK' | |
| 194 | + }, | |
| 195 | +] | |
| 196 | + | |
| 197 | +const operationNumberOrDate = [{ | |
| 198 | + label: '等于', | |
| 199 | + value: 'EQUAL', | |
| 200 | + symbol: '=' | |
| 201 | + }, | |
| 202 | + { | |
| 203 | + label: '不等于', | |
| 204 | + value: 'NOT_EQUAL', | |
| 205 | + symbol: '!=' | |
| 206 | + }, | |
| 207 | + { | |
| 208 | + label: '小于', | |
| 209 | + value: 'LESS', | |
| 210 | + symbol: '<' | |
| 211 | + }, | |
| 212 | + { | |
| 213 | + label: '小于等于', | |
| 214 | + value: 'LESS_OR_EQUAL', | |
| 215 | + symbol: '<=' | |
| 216 | + }, | |
| 217 | + { | |
| 218 | + label: '大于', | |
| 219 | + value: 'GREATER', | |
| 220 | + symbol: '>' | |
| 221 | + }, | |
| 222 | + { | |
| 223 | + label: '大于等于', | |
| 224 | + value: 'GREATER_OR_EQUAL', | |
| 225 | + symbol: '>=' | |
| 226 | + }, | |
| 227 | +]; | |
| 228 | + | |
| 229 | +const operationString = [{ | |
| 230 | + label: '等于', | |
| 231 | + value: 'EQUAL', | |
| 232 | + symbol: '=' | |
| 233 | + }, | |
| 234 | + { | |
| 235 | + label: '不等于', | |
| 236 | + value: 'NOT_EQUAL', | |
| 237 | + symbol: '!=' | |
| 238 | + }, | |
| 239 | + { | |
| 240 | + label: '开始于', | |
| 241 | + value: 'STARTS_WITH', | |
| 242 | + symbol: '开始于' | |
| 243 | + }, | |
| 244 | + { | |
| 245 | + label: '结束于', | |
| 246 | + value: 'ENDS_WITH', | |
| 247 | + symbol: '结束于' | |
| 248 | + }, | |
| 249 | + { | |
| 250 | + label: '包含', | |
| 251 | + value: 'CONTAINS', | |
| 252 | + symbol: '包含' | |
| 253 | + }, | |
| 254 | + { | |
| 255 | + label: '不包含', | |
| 256 | + value: 'NOT_CONTAINS', | |
| 257 | + symbol: '不包含' | |
| 258 | + }, | |
| 259 | +]; | |
| 260 | + | |
| 261 | +const operationBoolean = [{ | |
| 262 | + label: '等于', | |
| 263 | + value: 'EQUAL', | |
| 264 | + symbol: '=' | |
| 265 | + }, | |
| 266 | + { | |
| 267 | + label: '不等于', | |
| 268 | + value: 'NOT_EQUAL', | |
| 269 | + symbol: '!=' | |
| 270 | + }, | |
| 271 | +]; | |
| 272 | + | |
| 146 | 273 | export { |
| 147 | 274 | alertStatus, |
| 148 | 275 | deviceType, |
| 149 | 276 | alertLevel, |
| 150 | - timeArea | |
| 151 | -} | |
| 277 | + timeArea, | |
| 278 | + alarmSeverity, | |
| 279 | + alarmStatus, | |
| 280 | + operationNumberOrDate, | |
| 281 | + operationString, | |
| 282 | + operationBoolean | |
| 283 | +} | |
| \ No newline at end of file | ... | ... |
| 1 | -.alert-page { | |
| 1 | +.alarm-page { | |
| 2 | 2 | background: #f8f9fa; |
| 3 | 3 | .device-top { |
| 4 | 4 | padding: 10rpx 30rpx; |
| ... | ... | @@ -109,129 +109,8 @@ |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | -.device-list { | |
| 113 | - display: flex; | |
| 114 | - flex-direction: column; | |
| 115 | - padding-left: 18rpx; | |
| 116 | - justify-content: flex-start; | |
| 117 | - | |
| 118 | - .list-item { | |
| 119 | - width: 713rpx; | |
| 120 | - height: 233rpx; | |
| 121 | - background-color: #fff; | |
| 122 | - margin-top: 24rpx; | |
| 123 | - display: flex; | |
| 124 | - flex-direction: row; | |
| 125 | - border-radius: 10px; | |
| 126 | - justify-content: space-between; | |
| 127 | - | |
| 128 | - .item { | |
| 129 | - justify-content: flex-start; | |
| 130 | - flex-direction: column; | |
| 131 | - align-items: center; | |
| 132 | - height: 211rpx; | |
| 133 | - margin-top: 8rpx; | |
| 134 | - margin-left: 37rpx; | |
| 135 | - | |
| 136 | - .item-text { | |
| 137 | - width: 400rpx; | |
| 138 | - text-align: left; | |
| 139 | - margin-top: 13rpx; | |
| 140 | - line-height: 40rpx; | |
| 141 | - | |
| 142 | - .text { | |
| 143 | - color: #666666; | |
| 144 | - font-size: 15px; | |
| 145 | - } | |
| 146 | - | |
| 147 | - .text-three { | |
| 148 | - color: #333333; | |
| 149 | - font-size: 15px; | |
| 150 | - } | |
| 151 | 112 | |
| 152 | - .text-nine { | |
| 153 | - color: #999999; | |
| 154 | - font-size: 15px; | |
| 155 | - } | |
| 156 | - } | |
| 157 | 113 | |
| 158 | - .item-right { | |
| 159 | - flex-direction: row; | |
| 160 | - margin-top: -3rpx; | |
| 161 | - margin-right: 25rpx; | |
| 162 | - | |
| 163 | - .right-image { | |
| 164 | - width: 30rpx; | |
| 165 | - height: 30rpx; | |
| 166 | - margin-top: 20rpx; | |
| 167 | - margin-right: 5rpx; | |
| 168 | - } | |
| 169 | - | |
| 170 | - .right-text { | |
| 171 | - color: #333333; | |
| 172 | - font-size: 13px; | |
| 173 | - margin-left: 5rpx; | |
| 174 | - margin-top: 20rpx; | |
| 175 | - } | |
| 176 | - } | |
| 177 | - } | |
| 178 | - } | |
| 179 | -} | |
| 180 | - | |
| 181 | -.popup-page { | |
| 182 | - height: 1100rpx; | |
| 183 | - background: #ffffff; | |
| 184 | - border-radius: 20rpx; | |
| 185 | - overflow-y: scroll; | |
| 186 | - overflow-x: hidden; | |
| 187 | - | |
| 188 | - .popup-text { | |
| 189 | - text-align: center; | |
| 190 | - position: relative; | |
| 191 | - top: 68rpx; | |
| 192 | - margin-top: -40rpx; | |
| 193 | - | |
| 194 | - .text { | |
| 195 | - font-size: 16px; | |
| 196 | - color: #333333; | |
| 197 | - } | |
| 198 | - } | |
| 199 | - | |
| 200 | - .popup-alarm-page { | |
| 201 | - margin-top: 97rpx; | |
| 202 | - margin-left: 98rpx; | |
| 203 | - flex-direction: column; | |
| 204 | - justify-content: space-between; | |
| 205 | - .popup-alarm-text { | |
| 206 | - width: 750rpx; | |
| 207 | - margin-left: 14rpx; | |
| 208 | - .text { | |
| 209 | - color: #333333; | |
| 210 | - font-size: 14px; | |
| 211 | - } | |
| 212 | - } | |
| 213 | - .popup-alarm-child { | |
| 214 | - margin-top: 15rpx; | |
| 215 | - width: 750rpx; | |
| 216 | - height: 60rpx; | |
| 217 | - flex-wrap: wrap; | |
| 218 | - margin-left: -10rpx; | |
| 219 | - .alarm-text { | |
| 220 | - margin: 25rpx; | |
| 221 | - line-height: 50rpx; | |
| 222 | - text-align: center; | |
| 223 | - width: 180rpx; | |
| 224 | - height: 60rpx; | |
| 225 | - background-color: #f6f6f6; | |
| 226 | - border-radius: 32px; | |
| 227 | - .text { | |
| 228 | - color: #333333; | |
| 229 | - font-size: 13px; | |
| 230 | - } | |
| 231 | - } | |
| 232 | - } | |
| 233 | - } | |
| 234 | -} | |
| 235 | 114 | |
| 236 | 115 | .u-form { |
| 237 | 116 | width: 618rpx !important; | ... | ... |
pages/device/components/device-item.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="device-list"> | |
| 3 | + <view @click="$emit('openDeviceDetail',item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)" | |
| 4 | + class="list-item" v-for="item in list" :key="item.id"> | |
| 5 | + <view class="u-flex item"> | |
| 6 | + <view class="item-text text-clip"> | |
| 7 | + <view> | |
| 8 | + <text class="text-span-bold">{{ item.alias ? item.alias : item.name }}</text> | |
| 9 | + </view> | |
| 10 | + </view> | |
| 11 | + <view class="item-text text-clip"> | |
| 12 | + <view class="text-container"> | |
| 13 | + 设备编号: | |
| 14 | + <text class="text-span">{{ item.sn }}</text> | |
| 15 | + </view> | |
| 16 | + </view> | |
| 17 | + <view class="item-text text-clip"> | |
| 18 | + <view class="text-container"> | |
| 19 | + 所属组织: | |
| 20 | + <text class="text-span">{{ item.organizationDTO.name }}</text> | |
| 21 | + </view> | |
| 22 | + </view> | |
| 23 | + </view> | |
| 24 | + <view class="item right-item"> | |
| 25 | + <view class="u-flex" style="margin-top: -6rpx"> | |
| 26 | + <image class="right-image" :src="formatRightImage(item.deviceState)" /> | |
| 27 | + <view> | |
| 28 | + <text class="right-text" :style="{ color:formatColor(item.deviceState) }"> | |
| 29 | + {{ formatText(item.deviceState) }} | |
| 30 | + </text> | |
| 31 | + </view> | |
| 32 | + </view> | |
| 33 | + </view> | |
| 34 | + </view> | |
| 35 | + </view> | |
| 36 | +</template> | |
| 37 | + | |
| 38 | +<script> | |
| 39 | + export default { | |
| 40 | + props: { | |
| 41 | + list: { | |
| 42 | + type: Array, | |
| 43 | + default: [] | |
| 44 | + } | |
| 45 | + }, | |
| 46 | + methods: { | |
| 47 | + formatRightImage(deviceState) { | |
| 48 | + return deviceState === 'ONLINE' ? | |
| 49 | + '/static/online.png' : | |
| 50 | + deviceState === 'INACTIVE' ? | |
| 51 | + '/static/unonline.png' : | |
| 52 | + '/static/baojing.png' | |
| 53 | + }, | |
| 54 | + formatText(deviceState) { | |
| 55 | + return deviceState === 'ONLINE' ? '在线' : deviceState === 'INACTIVE' ? '待激活' : '离线' | |
| 56 | + }, | |
| 57 | + formatColor(deviceState) { | |
| 58 | + return deviceState === 'ONLINE' ? '#377DFF' : deviceState === 'INACTIVE' ? '#666666' : '#DE4437' | |
| 59 | + } | |
| 60 | + } | |
| 61 | + } | |
| 62 | +</script> | |
| 63 | + | |
| 64 | +<style lang="scss" scoped> | |
| 65 | + .device-list { | |
| 66 | + display: flex; | |
| 67 | + flex-direction: column; | |
| 68 | + padding-left: 20rpx; | |
| 69 | + | |
| 70 | + .list-item { | |
| 71 | + width: 713rpx; | |
| 72 | + height: 200rpx; | |
| 73 | + background-color: #fff; | |
| 74 | + margin-top: 24rpx; | |
| 75 | + display: flex; | |
| 76 | + border-radius: 10px; | |
| 77 | + justify-content: space-between; | |
| 78 | + | |
| 79 | + .item { | |
| 80 | + margin: 30rpx; | |
| 81 | + flex-direction: column; | |
| 82 | + justify-content: space-between; | |
| 83 | + | |
| 84 | + .item-text { | |
| 85 | + width: 450rpx; | |
| 86 | + | |
| 87 | + .text-container { | |
| 88 | + display: flex; | |
| 89 | + | |
| 90 | + .text-span { | |
| 91 | + color: #666; | |
| 92 | + font-size: 14px; | |
| 93 | + display: flex; | |
| 94 | + margin-left: 20rpx; | |
| 95 | + } | |
| 96 | + } | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + .text-span-bold { | |
| 101 | + color: #333; | |
| 102 | + font-size: 15px; | |
| 103 | + font-weight: bold; | |
| 104 | + } | |
| 105 | + } | |
| 106 | + } | |
| 107 | + | |
| 108 | + .right-item { | |
| 109 | + .right-image { | |
| 110 | + width: 30rpx; | |
| 111 | + height: 30rpx; | |
| 112 | + margin-top: 5rpx; | |
| 113 | + margin-right: 5rpx; | |
| 114 | + } | |
| 115 | + | |
| 116 | + .right-text { | |
| 117 | + color: #377dff; | |
| 118 | + font-size: 13px; | |
| 119 | + margin-left: 5rpx; | |
| 120 | + margin-top: 20rpx; | |
| 121 | + } | |
| 122 | + } | |
| 123 | + } | |
| 124 | + } | |
| 125 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/device/components/device-popup.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <u-popup @close="$emit('close')" closeable bgColor="#fff" :show="show" mode="bottom" :round="20" | |
| 3 | + @touchmove.stop.prevent="disabledScroll"> | |
| 4 | + <view class="filter" @touchmove.stop.prevent="disabledScroll"> | |
| 5 | + <view class="filter-title"><text>筛选条件</text></view> | |
| 6 | + <query-item :filterList="deviceStatus" title="设备状态" | |
| 7 | + @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></query-item> | |
| 8 | + <query-item :filterList="alarmStatus" title="告警状态" | |
| 9 | + @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></query-item> | |
| 10 | + <query-item :filterList="typeStatus" title="设备类型" | |
| 11 | + @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></query-item> | |
| 12 | + <view class="button-group"> | |
| 13 | + <view> | |
| 14 | + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" | |
| 15 | + @click="resetFilter"></u-button> | |
| 16 | + </view> | |
| 17 | + <view> | |
| 18 | + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button> | |
| 19 | + </view> | |
| 20 | + </view> | |
| 21 | + </view> | |
| 22 | + </u-popup> | |
| 23 | +</template> | |
| 24 | + | |
| 25 | +<script> | |
| 26 | + import queryItem from './query-item.vue' | |
| 27 | + import { | |
| 28 | + deviceStatus, | |
| 29 | + alarmStatus, | |
| 30 | + typeStatus | |
| 31 | + } from '../config/data.js' | |
| 32 | + | |
| 33 | + export default { | |
| 34 | + components: { | |
| 35 | + queryItem | |
| 36 | + }, | |
| 37 | + props: { | |
| 38 | + show: Boolean | |
| 39 | + }, | |
| 40 | + data() { | |
| 41 | + return { | |
| 42 | + deviceStatus, | |
| 43 | + alarmStatus, | |
| 44 | + typeStatus | |
| 45 | + } | |
| 46 | + }, | |
| 47 | + methods: { | |
| 48 | + disabledScroll() { | |
| 49 | + return; | |
| 50 | + }, | |
| 51 | + handleClickTag(currentIndex, list) { | |
| 52 | + list.map((item, index) => { | |
| 53 | + item.checked = index === currentIndex; | |
| 54 | + }); | |
| 55 | + }, | |
| 56 | + resetFilter() { | |
| 57 | + const {deviceStatus,alarmStatus,typeStatus} = this; | |
| 58 | + [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index ===0))); | |
| 59 | + }, | |
| 60 | + confirmFilter() { | |
| 61 | + const deviceState = this.deviceStatus.find(item => item.checked); | |
| 62 | + const alarmStatus = this.alarmStatus.find(item => item.checked); | |
| 63 | + const deviceType = this.typeStatus.find(item => item.checked); | |
| 64 | + this.$emit('queryCondition', { | |
| 65 | + deviceState: deviceState.type ? deviceState.type : undefined, | |
| 66 | + deviceType: deviceType.type ? deviceType.type : undefined, | |
| 67 | + alarmStatus: alarmStatus.type === 0 || alarmStatus.type === 1 ? alarmStatus.type : undefined | |
| 68 | + }) | |
| 69 | + }, | |
| 70 | + } | |
| 71 | + } | |
| 72 | +</script> | |
| 73 | + | |
| 74 | +<style lang="scss" scoped> | |
| 75 | + .filter { | |
| 76 | + padding: 0 30rpx; | |
| 77 | + | |
| 78 | + .filter-title { | |
| 79 | + text-align: center; | |
| 80 | + margin-top: 14px; | |
| 81 | + font-size: 16px; | |
| 82 | + font-weight: 700; | |
| 83 | + } | |
| 84 | + | |
| 85 | + .button-group { | |
| 86 | + display: flex; | |
| 87 | + margin-top: 40rpx; | |
| 88 | + justify-content: space-between; | |
| 89 | + | |
| 90 | + view { | |
| 91 | + width: 330rpx; | |
| 92 | + } | |
| 93 | + } | |
| 94 | + } | |
| 95 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/device/components/query-item.vue
renamed from
pages/device/FilterItem.vue
| 1 | -<template> | |
| 2 | - <view class="filter-item"> | |
| 3 | - <view class="filter-title"> | |
| 4 | - <text>{{ title }}</text> | |
| 5 | - </view> | |
| 6 | - <view class="filter-list"> | |
| 7 | - <view v-for="(item, index) in filterList" :key="index" @click="radioClick(index)" :class="['tag-item', { checked: item.checked, 'mr-30': (index + 1) % 3 !== 0 }]"> | |
| 8 | - {{ item.name }} | |
| 9 | - </view> | |
| 10 | - </view> | |
| 11 | - </view> | |
| 12 | -</template> | |
| 13 | - | |
| 14 | -<script> | |
| 15 | -export default { | |
| 16 | - props: { | |
| 17 | - title: { | |
| 18 | - type: String, | |
| 19 | - default: '' | |
| 20 | - }, | |
| 21 | - filterList: { | |
| 22 | - type: Array, | |
| 23 | - default: () => [] | |
| 24 | - } | |
| 25 | - }, | |
| 26 | - methods: { | |
| 27 | - radioClick(currentIndex) { | |
| 28 | - this.$emit('clickTag', currentIndex); | |
| 29 | - } | |
| 30 | - } | |
| 31 | -}; | |
| 32 | -</script> | |
| 33 | - | |
| 34 | -<style lang="scss" scoped> | |
| 35 | -.filter-item { | |
| 36 | - margin-top: 40rpx; | |
| 37 | - .filter-title { | |
| 38 | - color: #333; | |
| 39 | - font-size: 14px; | |
| 40 | - font-weight: 700; | |
| 41 | - } | |
| 42 | - .filter-list { | |
| 43 | - display: flex; | |
| 44 | - flex-wrap: wrap; | |
| 45 | - .tag-item { | |
| 46 | - margin-top: 30rpx; | |
| 47 | - width: 210rpx; | |
| 48 | - height: 68rpx; | |
| 49 | - border-radius: 32rpx; | |
| 50 | - display: flex; | |
| 51 | - justify-content: center; | |
| 52 | - align-items: center; | |
| 53 | - color: #333; | |
| 54 | - font-size: 13px; | |
| 55 | - border: 1px solid #fff; | |
| 56 | - background-color: #f6f6f6; | |
| 57 | - } | |
| 58 | - .checked { | |
| 59 | - border: 1px solid #377dff4d; | |
| 60 | - background-color: #377dff0d; | |
| 61 | - color: #377dffff; | |
| 62 | - } | |
| 63 | - .mr-30 { | |
| 64 | - margin-right: 30rpx; | |
| 65 | - } | |
| 66 | - } | |
| 67 | -} | |
| 68 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="query-item"> | |
| 3 | + <view class="query-title"> | |
| 4 | + <text>{{ title }}</text> | |
| 5 | + </view> | |
| 6 | + <view class="query-list"> | |
| 7 | + <view v-for="(item, index) in filterList" :key="index" @click="itemClick(index)" | |
| 8 | + :class="['tag-item', { checked: item.checked, 'mr-30': (index + 1) % 3 !== 0 }]"> | |
| 9 | + {{ item.name }} | |
| 10 | + </view> | |
| 11 | + </view> | |
| 12 | + </view> | |
| 13 | +</template> | |
| 14 | + | |
| 15 | +<script> | |
| 16 | + export default { | |
| 17 | + props: { | |
| 18 | + title: { | |
| 19 | + type: String, | |
| 20 | + default: '' | |
| 21 | + }, | |
| 22 | + filterList: { | |
| 23 | + type: Array, | |
| 24 | + default: () => [] | |
| 25 | + } | |
| 26 | + }, | |
| 27 | + methods: { | |
| 28 | + itemClick(currentIndex) { | |
| 29 | + this.$emit('clickTag', currentIndex); | |
| 30 | + } | |
| 31 | + } | |
| 32 | + }; | |
| 33 | +</script> | |
| 34 | + | |
| 35 | +<style lang="scss" scoped> | |
| 36 | + .query-item { | |
| 37 | + margin-top: 40rpx; | |
| 38 | + | |
| 39 | + .query-title { | |
| 40 | + color: #333; | |
| 41 | + font-size: 14px; | |
| 42 | + font-weight: 700; | |
| 43 | + } | |
| 44 | + | |
| 45 | + .query-list { | |
| 46 | + display: flex; | |
| 47 | + flex-wrap: wrap; | |
| 48 | + | |
| 49 | + .tag-item { | |
| 50 | + margin-top: 30rpx; | |
| 51 | + width: 210rpx; | |
| 52 | + height: 68rpx; | |
| 53 | + border-radius: 32rpx; | |
| 54 | + display: flex; | |
| 55 | + justify-content: center; | |
| 56 | + align-items: center; | |
| 57 | + color: #333; | |
| 58 | + font-size: 13px; | |
| 59 | + border: 1px solid #fff; | |
| 60 | + background-color: #f6f6f6; | |
| 61 | + } | |
| 62 | + | |
| 63 | + .checked { | |
| 64 | + border: 1px solid #377dff4d; | |
| 65 | + background-color: #377dff0d; | |
| 66 | + color: #377dffff; | |
| 67 | + } | |
| 68 | + | |
| 69 | + .mr-30 { | |
| 70 | + margin-right: 30rpx; | |
| 71 | + } | |
| 72 | + } | |
| 73 | + } | |
| 74 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/device/config/data.js
0 → 100644
| 1 | +const deviceStatus = [{ | |
| 2 | + checked: true, | |
| 3 | + name: '全部', | |
| 4 | + type: '' | |
| 5 | + }, | |
| 6 | + { | |
| 7 | + checked: false, | |
| 8 | + name: '在线', | |
| 9 | + type: 'ONLINE' | |
| 10 | + }, | |
| 11 | + { | |
| 12 | + checked: false, | |
| 13 | + name: '离线', | |
| 14 | + type: 'OFFLINE' | |
| 15 | + }, | |
| 16 | + { | |
| 17 | + checked: false, | |
| 18 | + name: '待激活', | |
| 19 | + type: 'INACTIVE' | |
| 20 | + } | |
| 21 | +] | |
| 22 | +const alarmStatus = [{ | |
| 23 | + checked: true, | |
| 24 | + name: '全部', | |
| 25 | + type: '' | |
| 26 | + }, | |
| 27 | + { | |
| 28 | + checked: false, | |
| 29 | + name: '告警', | |
| 30 | + type: 1 | |
| 31 | + }, | |
| 32 | + { | |
| 33 | + checked: false, | |
| 34 | + name: '正常', | |
| 35 | + type: 0 | |
| 36 | + } | |
| 37 | +] | |
| 38 | +const typeStatus = [{ | |
| 39 | + checked: true, | |
| 40 | + name: '全部', | |
| 41 | + type: '' | |
| 42 | + }, | |
| 43 | + | |
| 44 | + { | |
| 45 | + checked: false, | |
| 46 | + name: '直连设备', | |
| 47 | + type: 'DIRECT_CONNECTION' | |
| 48 | + }, | |
| 49 | + { | |
| 50 | + checked: false, | |
| 51 | + name: '网关设备', | |
| 52 | + type: 'GATEWAY' | |
| 53 | + }, | |
| 54 | + { | |
| 55 | + checked: false, | |
| 56 | + name: '网关子设备', | |
| 57 | + type: 'SENSOR' | |
| 58 | + } | |
| 59 | +] | |
| 60 | + | |
| 61 | +export { | |
| 62 | + deviceStatus, | |
| 63 | + alarmStatus, | |
| 64 | + typeStatus | |
| 65 | +} | |
| \ No newline at end of file | ... | ... |
| 1 | 1 | <template> |
| 2 | 2 | <view class="device-page"> |
| 3 | - <u-sticky> | |
| 4 | - <view class="device-top"> | |
| 5 | - <view class="search"> | |
| 6 | - <view> | |
| 7 | - <view class="search-left"> | |
| 8 | - <u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" shape="circle" | |
| 9 | - @change="inputChanged"></u--input> | |
| 10 | - </view> | |
| 11 | - </view> | |
| 12 | - <view @click="openSearchDialog" class="search-right"> | |
| 13 | - <text>筛选</text> | |
| 14 | - <image src="../../static/shaixuan.png" /> | |
| 15 | - </view> | |
| 16 | - </view> | |
| 17 | - <u-line /> | |
| 18 | - <view class="org"> | |
| 19 | - <u-cell @click="openOrg" isLink title="组织关系" :border="false"> | |
| 20 | - <view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;"> | |
| 21 | - <image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image> | |
| 22 | - <view style="margin-left: 10rpx; color: #666;"> | |
| 23 | - 设备数: | |
| 24 | - <text style="margin-left: 20rpx;">{{ total }}</text> | |
| 25 | - </view> | |
| 26 | - </view> | |
| 27 | - </u-cell> | |
| 28 | - </view> | |
| 29 | - </view> | |
| 30 | - </u-sticky> | |
| 3 | + <!-- 设备头部 --> | |
| 4 | + <header-search @openOrg="openOrg" @openSearchDialog="openSearchDialog" :total="total" :totalText="totalText"> | |
| 5 | + <!-- 不能写在封装组件里传placeholder,mp-wenxin端编译要报错 --> | |
| 6 | + <u--input prefixIcon="search" placeholder="请输入设备SN或名称搜索" shape="circle" @change="inputChanged"> | |
| 7 | + </u--input> | |
| 8 | + </header-search> | |
| 9 | + <!-- 设备分页 --> | |
| 31 | 10 | <mescroll-body ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback" |
| 32 | 11 | @up="upCallback"> |
| 33 | - <view class="device-list"> | |
| 34 | - <view @click="openDeviceDetail(item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)" | |
| 35 | - class="list-item" v-for="item in list" :key="item.id"> | |
| 36 | - <view class="u-flex item" style=" | |
| 37 | - justify-content: flex-start; | |
| 38 | - flex-direction: column; | |
| 39 | - align-items: center; | |
| 40 | - "> | |
| 41 | - <view style="width: 450rpx; text-align: left"> | |
| 42 | - <view class="text-clip" style="width:450rpx"> | |
| 43 | - <text class="" | |
| 44 | - style="color: #333; font-size: 15px;font-weight: bold;">{{ item.alias ? item.alias : item.name }}</text> | |
| 45 | - </view> | |
| 46 | - | |
| 47 | - </view> | |
| 48 | - <view style="width: 450rpx; text-align: left; margin-top: 10rpx"> | |
| 49 | - <view style="color: #666; font-size: 14px;display: flex;"> | |
| 50 | - 设备编号: | |
| 51 | - <view style="margin-left:16rpx">{{ item.sn }}</view> | |
| 52 | - </view> | |
| 53 | - </view> | |
| 54 | - <view style="width: 450rpx; text-align: left; margin-top: 10rpx"> | |
| 55 | - <view style="color: #666; font-size: 14px;display: flex;"> | |
| 56 | - 所属组织: | |
| 57 | - <view style="margin-left:16rpx">{{ item.organizationDTO.name }}</view> | |
| 58 | - </view> | |
| 59 | - </view> | |
| 60 | - </view> | |
| 61 | - <view class="item"> | |
| 62 | - <view class="u-flex" style="margin-top: -6rpx"> | |
| 63 | - <image style=" | |
| 64 | - width: 30rpx; | |
| 65 | - height: 30rpx; | |
| 66 | - margin-top: 5rpx; | |
| 67 | - margin-right: 5rpx; | |
| 68 | - " :src=" | |
| 69 | - item.deviceState === 'ONLINE' | |
| 70 | - ? '../../static/online.png' | |
| 71 | - : item.deviceState === 'INACTIVE' | |
| 72 | - ? '../../static/unonline.png' | |
| 73 | - : '../../static/baojing.png' | |
| 74 | - " /> | |
| 75 | - | |
| 76 | - <view> | |
| 77 | - <text style=" | |
| 78 | - color: #377dff; | |
| 79 | - font-size: 13px; | |
| 80 | - margin-left: 5rpx; | |
| 81 | - margin-top: 20rpx; | |
| 82 | - " :style="{ color: item.deviceState === 'ONLINE' ? '#377DFF' : item.deviceState === 'INACTIVE' ? '#666666' : '#DE4437' }"> | |
| 83 | - {{ item.deviceState === 'ONLINE' ? '在线' : item.deviceState === 'INACTIVE' ? '待激活' : '离线' }} | |
| 84 | - </text> | |
| 85 | - </view> | |
| 86 | - </view> | |
| 87 | - </view> | |
| 88 | - </view> | |
| 89 | - </view> | |
| 12 | + <device-item :list="list" @openDeviceDetail="openDeviceDetail"></device-item> | |
| 90 | 13 | </mescroll-body> |
| 14 | + <view style="height: 20rpx"></view> | |
| 91 | 15 | <!-- 设备筛选 --> |
| 92 | - <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20" | |
| 93 | - @touchmove.stop.prevent="disabledScroll"> | |
| 94 | - <view class="filter" @touchmove.stop.prevent="disabledScroll"> | |
| 95 | - <view class="filter-title"><text>筛选条件</text></view> | |
| 96 | - <FilterItem :filterList="deviceStatus" title="设备状态" | |
| 97 | - @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></FilterItem> | |
| 98 | - <FilterItem :filterList="alarmStatus" title="告警状态" | |
| 99 | - @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem> | |
| 100 | - <FilterItem :filterList="typeStatus" title="设备类型" | |
| 101 | - @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem> | |
| 102 | - <view class="button-group"> | |
| 103 | - <view> | |
| 104 | - <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" | |
| 105 | - @click="resetFilter"></u-button> | |
| 106 | - </view> | |
| 107 | - <view> | |
| 108 | - <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button> | |
| 109 | - </view> | |
| 110 | - </view> | |
| 111 | - </view> | |
| 112 | - </u-popup> | |
| 16 | + <device-popup ref="devicePopupRef" :show="show" @close="close" | |
| 17 | + @queryCondition="getQueryCondition"></device-popup> | |
| 113 | 18 | <f-tabbar></f-tabbar> |
| 114 | 19 | </view> |
| 115 | 20 | </template> |
| 116 | 21 | |
| 117 | 22 | <script> |
| 118 | 23 | import fTabbar from '@/components/module/f-tabbar/f-tabbar'; |
| 119 | - import FilterItem from './FilterItem.vue'; | |
| 120 | 24 | import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; |
| 121 | - import { | |
| 122 | - debounce | |
| 123 | - } from '@/plugins/throttle.js'; | |
| 124 | 25 | import api from '@/api/index.js' |
| 26 | + import { | |
| 27 | + useNavigateTo | |
| 28 | + } from '@/plugins/utils.js' | |
| 29 | + import deviceItem from './components/device-item.vue' | |
| 30 | + import devicePopup from './components/device-popup.vue' | |
| 125 | 31 | |
| 126 | 32 | export default { |
| 127 | 33 | mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) |
| 128 | 34 | components: { |
| 129 | 35 | fTabbar, |
| 130 | - FilterItem | |
| 36 | + deviceItem, | |
| 37 | + devicePopup | |
| 131 | 38 | }, |
| 132 | 39 | data() { |
| 133 | 40 | return { |
| 41 | + totalText: '设备数', | |
| 134 | 42 | downOption: { |
| 135 | 43 | auto: false //是否在初始化后,自动执行downCallback; 默认true |
| 136 | 44 | }, |
| ... | ... | @@ -139,143 +47,91 @@ |
| 139 | 47 | auto: false // 不自动加载 |
| 140 | 48 | }, |
| 141 | 49 | show: false, |
| 142 | - deviceStatus: [{ | |
| 143 | - checked: true, | |
| 144 | - name: '全部', | |
| 145 | - type: '' | |
| 146 | - }, | |
| 147 | - { | |
| 148 | - checked: false, | |
| 149 | - name: '在线', | |
| 150 | - type: 'ONLINE' | |
| 151 | - }, | |
| 152 | - { | |
| 153 | - checked: false, | |
| 154 | - name: '离线', | |
| 155 | - type: 'OFFLINE' | |
| 156 | - }, | |
| 157 | - { | |
| 158 | - checked: false, | |
| 159 | - name: '待激活', | |
| 160 | - type: 'INACTIVE' | |
| 161 | - } | |
| 162 | - ], | |
| 163 | - alarmStatus: [{ | |
| 164 | - checked: true, | |
| 165 | - name: '全部', | |
| 166 | - type: '' | |
| 167 | - }, | |
| 168 | - { | |
| 169 | - checked: false, | |
| 170 | - name: '告警', | |
| 171 | - type: 1 | |
| 172 | - }, | |
| 173 | - { | |
| 174 | - checked: false, | |
| 175 | - name: '正常', | |
| 176 | - type: 0 | |
| 177 | - } | |
| 178 | - ], | |
| 179 | - typeStatus: [{ | |
| 180 | - checked: true, | |
| 181 | - name: '全部', | |
| 182 | - type: '' | |
| 183 | - }, | |
| 184 | - | |
| 185 | - { | |
| 186 | - checked: false, | |
| 187 | - name: '直连设备', | |
| 188 | - type: 'DIRECT_CONNECTION' | |
| 189 | - }, | |
| 190 | - { | |
| 191 | - checked: false, | |
| 192 | - name: '网关设备', | |
| 193 | - type: 'GATEWAY' | |
| 194 | - }, | |
| 195 | - { | |
| 196 | - checked: false, | |
| 197 | - name: '网关子设备', | |
| 198 | - type: 'SENSOR' | |
| 199 | - } | |
| 200 | - ], | |
| 201 | 50 | total: 0, |
| 202 | 51 | list: [], |
| 203 | 52 | page: { |
| 204 | 53 | num: 0, |
| 205 | 54 | size: 10 |
| 206 | 55 | }, |
| 207 | - deviceState: '', | |
| 208 | - deviceName: '' | |
| 56 | + deviceName: '', | |
| 57 | + ordId: '', | |
| 58 | + conditions: {} | |
| 209 | 59 | }; |
| 210 | 60 | }, |
| 211 | - async onLoad(options) { | |
| 61 | + onLoad(e) { | |
| 212 | 62 | // 隐藏原生的tabbar |
| 213 | 63 | uni.hideTabBar(); |
| 214 | - if(getApp().getBindNot()){ | |
| 64 | + if (getApp().getBindNot()) { | |
| 215 | 65 | return |
| 216 | 66 | } |
| 217 | - this.page.num = 1; | |
| 218 | - const { | |
| 219 | - deviceState | |
| 220 | - } = options; | |
| 221 | - this.deviceState = deviceState; | |
| 222 | - if (deviceState) { | |
| 223 | - this.deviceStatus.forEach(item => { | |
| 224 | - item.type === deviceState ? (item.checked = true) : (item.checked = false); | |
| 225 | - }); | |
| 226 | - await this.loadData(1, { | |
| 227 | - deviceState | |
| 228 | - }); | |
| 67 | + if (!e.deviceState) { | |
| 68 | + this.loadData(1); | |
| 229 | 69 | } else { |
| 230 | - await this.loadData(1); | |
| 231 | - } | |
| 232 | - if (!this.list.length) { | |
| 233 | - this.mescroll.showEmpty(); | |
| 70 | + let params = JSON.parse(e.deviceState); | |
| 71 | + this.conditions = { | |
| 72 | + deviceState: params | |
| 73 | + } | |
| 74 | + this.loadData(1, { | |
| 75 | + deviceState: params | |
| 76 | + }); | |
| 234 | 77 | } |
| 235 | 78 | }, |
| 236 | 79 | onShow() { |
| 237 | - if(getApp().getBindNot()){ | |
| 80 | + if (getApp().getBindNot()) { | |
| 238 | 81 | return |
| 239 | 82 | } |
| 240 | - if (this.orgId) { | |
| 83 | + if (this.ordId) { | |
| 241 | 84 | this.loadData(1, { |
| 242 | - organizationId: this.orgId | |
| 85 | + organizationId: this.ordId | |
| 243 | 86 | }); |
| 87 | + this.conditions = { | |
| 88 | + organizationId: this.ordId | |
| 89 | + } | |
| 244 | 90 | } |
| 245 | 91 | }, |
| 246 | 92 | methods: { |
| 247 | - disabledScroll() { | |
| 248 | - return; | |
| 93 | + inputChanged(e) { | |
| 94 | + this.page.num = 1; | |
| 95 | + this.deviceName = e; | |
| 96 | + this.conditions = { | |
| 97 | + deviceName: e | |
| 98 | + } | |
| 99 | + this.loadData(1, { | |
| 100 | + name: this.deviceName | |
| 101 | + }); | |
| 102 | + }, | |
| 103 | + resetQuery() { | |
| 104 | + this.$refs.devicePopupRef.resetFilter() | |
| 105 | + this.ordId = '' | |
| 106 | + this.deviceName = '' | |
| 107 | + this.conditions = {} | |
| 108 | + }, | |
| 109 | + getQueryCondition(value) { | |
| 110 | + const condition = Object.values(value) | |
| 111 | + this.page.num = 1; | |
| 112 | + this.loadData(this.page.num, value); | |
| 113 | + this.conditions = value | |
| 114 | + this.close() | |
| 249 | 115 | }, |
| 250 | - /*下拉刷新的回调 */ | |
| 251 | 116 | downCallback() { |
| 252 | - this.deviceName = ''; | |
| 253 | - this.orgId = ''; | |
| 254 | - //联网加载数据 | |
| 255 | 117 | this.list = []; |
| 256 | 118 | this.page.num = 1; |
| 257 | - //联网加载数据 | |
| 258 | - this.resetFilter(); | |
| 259 | 119 | this.loadData(this.page.num); |
| 120 | + this.resetQuery(); | |
| 260 | 121 | }, |
| 261 | - | |
| 262 | - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 263 | 122 | upCallback() { |
| 264 | - //联网加载数据 | |
| 265 | - this.page.num += 1; | |
| 266 | - const deviceState = this.deviceStatus.find(item => item.checked); | |
| 267 | - const alarmStatus = this.alarmStatus.find(item => item.checked); | |
| 268 | - const deviceType = this.typeStatus.find(item => item.checked); | |
| 269 | - this.loadData(this.page.num, { | |
| 270 | - deviceState: deviceState.type ? deviceState.type : undefined, | |
| 271 | - deviceType: deviceType.type ? deviceType.type : undefined, | |
| 272 | - alarmStatus: alarmStatus.type === 0 || alarmStatus.type === 1 ? alarmStatus.type : | |
| 273 | - undefined, | |
| 274 | - name: this.deviceName == null ? null : this.deviceName, | |
| 275 | - organizationId: this.orgId == null ? null : this.orgId | |
| 276 | - }); | |
| 123 | + const condition = Object.values(this.conditions) | |
| 124 | + if (condition.length === 0) { | |
| 125 | + this.page.num += 1; | |
| 126 | + this.loadData(this.page.num); | |
| 127 | + } else if (condition.filter(Boolean).length > 0) { | |
| 128 | + this.page.num += 1; | |
| 129 | + this.loadData(this.page.num, this.conditions); | |
| 130 | + } else { | |
| 131 | + this.page.num += 1; | |
| 132 | + this.loadData(this.page.num); | |
| 133 | + } | |
| 277 | 134 | }, |
| 278 | - | |
| 279 | 135 | //获取设备 |
| 280 | 136 | async loadData(pageNo, params = {}) { |
| 281 | 137 | try { |
| ... | ... | @@ -307,54 +163,22 @@ |
| 307 | 163 | } |
| 308 | 164 | }, |
| 309 | 165 | openOrg() { |
| 310 | - uni.navigateTo({ | |
| 311 | - url: './org/org' | |
| 312 | - }); | |
| 166 | + useNavigateTo('/pages/organization/organization') | |
| 313 | 167 | }, |
| 314 | 168 | close() { |
| 315 | 169 | this.show = false; |
| 316 | 170 | }, |
| 317 | 171 | openSearchDialog() { |
| 318 | 172 | this.show = true; |
| 173 | + this.$nextTick(() => { | |
| 174 | + this.resetQuery(); | |
| 175 | + }) | |
| 319 | 176 | }, |
| 320 | 177 | openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) { |
| 321 | 178 | uni.navigateTo({ |
| 322 | - url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}` | |
| 179 | + url: `/device-subpackage/device-detail/device-detail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}` | |
| 323 | 180 | }); |
| 324 | 181 | }, |
| 325 | - handleClickTag(currentIndex, list) { | |
| 326 | - list.map((item, index) => { | |
| 327 | - item.checked = index === currentIndex; | |
| 328 | - }); | |
| 329 | - }, | |
| 330 | - resetFilter() { | |
| 331 | - const { | |
| 332 | - deviceStatus, | |
| 333 | - alarmStatus, | |
| 334 | - typeStatus | |
| 335 | - } = this; | |
| 336 | - [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index === | |
| 337 | - 0))); | |
| 338 | - }, | |
| 339 | - confirmFilter() { | |
| 340 | - const deviceState = this.deviceStatus.find(item => item.checked); | |
| 341 | - const alarmStatus = this.alarmStatus.find(item => item.checked); | |
| 342 | - const deviceType = this.typeStatus.find(item => item.checked); | |
| 343 | - this.loadData(1, { | |
| 344 | - deviceState: deviceState.type ? deviceState.type : undefined, | |
| 345 | - deviceType: deviceType.type ? deviceType.type : undefined, | |
| 346 | - alarmStatus: alarmStatus.type === 0 || alarmStatus.type === 1 ? alarmStatus.type : | |
| 347 | - undefined | |
| 348 | - }); | |
| 349 | - this.show = false; | |
| 350 | - }, | |
| 351 | - inputChanged(e) { | |
| 352 | - this.page.num = 1; | |
| 353 | - this.deviceName = e; | |
| 354 | - this.loadData(1, { | |
| 355 | - name: this.deviceName | |
| 356 | - }); | |
| 357 | - } | |
| 358 | 182 | } |
| 359 | 183 | }; |
| 360 | 184 | </script> |
| ... | ... | @@ -396,45 +220,4 @@ |
| 396 | 220 | } |
| 397 | 221 | } |
| 398 | 222 | } |
| 399 | - | |
| 400 | - .device-list { | |
| 401 | - display: flex; | |
| 402 | - flex-direction: column; | |
| 403 | - padding-left: 20rpx; | |
| 404 | - | |
| 405 | - .list-item { | |
| 406 | - width: 713rpx; | |
| 407 | - height: 200rpx; | |
| 408 | - background-color: #fff; | |
| 409 | - margin-top: 24rpx; | |
| 410 | - display: flex; | |
| 411 | - border-radius: 10px; | |
| 412 | - justify-content: space-between; | |
| 413 | - | |
| 414 | - .item { | |
| 415 | - margin: 30rpx; | |
| 416 | - } | |
| 417 | - } | |
| 418 | - } | |
| 419 | - | |
| 420 | - .filter { | |
| 421 | - padding: 0 30rpx; | |
| 422 | - | |
| 423 | - .filter-title { | |
| 424 | - text-align: center; | |
| 425 | - margin-top: 14px; | |
| 426 | - font-size: 16px; | |
| 427 | - font-weight: 700; | |
| 428 | - } | |
| 429 | - | |
| 430 | - .button-group { | |
| 431 | - display: flex; | |
| 432 | - margin-top: 40rpx; | |
| 433 | - justify-content: space-between; | |
| 434 | - | |
| 435 | - view { | |
| 436 | - width: 330rpx; | |
| 437 | - } | |
| 438 | - } | |
| 439 | - } | |
| 440 | -</style> | |
| 223 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/device/org/org.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <view class="org-content"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view> | |
| 6 | - <luyj-tree @sendValue="confirm" :is-check="isCheck" search-placeholder="请输入搜索内容" :search-if="true" v-slot:default="{ item }" :max="max" :trees="tree" :nodes="false"> | |
| 7 | - <view> | |
| 8 | - <view class="content-item"> | |
| 9 | - <view class="word">{{ item.name }}</view> | |
| 10 | - </view> | |
| 11 | - </view> | |
| 12 | - </luyj-tree> | |
| 13 | - <mescroll-empty v-if="!tree.length" /> | |
| 14 | - </view> | |
| 15 | - </view> | |
| 16 | -</template> | |
| 17 | - | |
| 18 | -<script> | |
| 19 | -import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 20 | -import { transOrgFunc } from '@/config/common.js'; | |
| 21 | -export default { | |
| 22 | - components: { | |
| 23 | - fTabbar | |
| 24 | - }, | |
| 25 | - data() { | |
| 26 | - return { | |
| 27 | - isCheck: true, // 是否可选 | |
| 28 | - tree: [], | |
| 29 | - max: 5, | |
| 30 | - id: '' | |
| 31 | - }; | |
| 32 | - }, | |
| 33 | - onLoad(e) { | |
| 34 | - // 隐藏原生的tabbar | |
| 35 | - uni.hideTabBar(); | |
| 36 | - this.loadData(); | |
| 37 | - }, | |
| 38 | - methods: { | |
| 39 | - loadData() { | |
| 40 | - uni.$u.http | |
| 41 | - .get('/yt/organization/me/list') | |
| 42 | - .then(res => { | |
| 43 | - if (res) { | |
| 44 | - const list = transOrgFunc(res); | |
| 45 | - this.tree = list; | |
| 46 | - } | |
| 47 | - }) | |
| 48 | - .catch(e => { | |
| 49 | - // uni.$u.toast(e.data.message); | |
| 50 | - }); | |
| 51 | - }, | |
| 52 | - confirm(val) { | |
| 53 | - this.id = val[0].id; | |
| 54 | - let pages = getCurrentPages(); //获取所有页面栈实例列表 | |
| 55 | - let nowPage = pages[pages.length - 1]; //当前页页面实例 | |
| 56 | - let prevPage = pages[pages.length - 2]; //上一页页面实例 | |
| 57 | - prevPage.$vm.orgId = this.id; | |
| 58 | - uni.navigateBack({ | |
| 59 | - delta: 1 | |
| 60 | - }); | |
| 61 | - } | |
| 62 | - } | |
| 63 | -}; | |
| 64 | -</script> | |
| 65 | - | |
| 66 | -<style lang="scss" scoped> | |
| 67 | -.org-content { | |
| 68 | - padding: 0 10rpx; | |
| 69 | -} | |
| 70 | -</style> |
pages/index/camera/org/org.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <view class="org-content"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view> | |
| 6 | - <luyj-tree @sendValue="confirm" :is-check="isCheck" search-placeholder="请输入搜索内容" :search-if="true" v-slot:default="{ item }" :max="max" :trees="tree"> | |
| 7 | - <view> | |
| 8 | - <view class="content-item"> | |
| 9 | - <view class="word">{{ item.name }}</view> | |
| 10 | - </view> | |
| 11 | - </view> | |
| 12 | - </luyj-tree> | |
| 13 | - </view> | |
| 14 | - </view> | |
| 15 | -</template> | |
| 16 | - | |
| 17 | -<script> | |
| 18 | -import { transOrgFunc } from '@/config/common.js'; | |
| 19 | - | |
| 20 | -export default { | |
| 21 | - data() { | |
| 22 | - return { | |
| 23 | - isCheck: true, // 是否可选 | |
| 24 | - tree: [], | |
| 25 | - max: 5, | |
| 26 | - id: '' | |
| 27 | - }; | |
| 28 | - }, | |
| 29 | - onLoad(e) { | |
| 30 | - // 隐藏原生的tabbar | |
| 31 | - uni.hideTabBar(); | |
| 32 | - this.loadData(); | |
| 33 | - }, | |
| 34 | - methods: { | |
| 35 | - loadData() { | |
| 36 | - uni.$u.http | |
| 37 | - .get('/yt/organization/me/list') | |
| 38 | - .then(res => { | |
| 39 | - if (res) { | |
| 40 | - const list = transOrgFunc(res); | |
| 41 | - this.tree = list; | |
| 42 | - } | |
| 43 | - }) | |
| 44 | - .catch(e => {}); | |
| 45 | - }, | |
| 46 | - confirm(val) { | |
| 47 | - this.id = val[0].id; | |
| 48 | - let pages = getCurrentPages(); //获取所有页面栈实例列表 | |
| 49 | - let nowPage = pages[pages.length - 1]; //当前页页面实例 | |
| 50 | - let prevPage = pages[pages.length - 2]; //上一页页面实例 | |
| 51 | - prevPage.$vm.ordId = this.id; | |
| 52 | - uni.navigateBack({ | |
| 53 | - delta: 1 | |
| 54 | - }); | |
| 55 | - } | |
| 56 | - } | |
| 57 | -}; | |
| 58 | -</script> | |
| 59 | - | |
| 60 | -<style lang="scss" scoped> | |
| 61 | -.org-content { | |
| 62 | - padding: 0 10rpx; | |
| 63 | -} | |
| 64 | -</style> |
pages/index/components/camera/camera.vue
renamed from
pages/index/camera/camera.vue
| 1 | -<template> | |
| 2 | - <view class="camera-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view class="org-sty"> | |
| 6 | - <view @click="openOrg" class="org-item"> | |
| 7 | - <view class="u-flex org-contact"><text class="text">组织关系</text></view> | |
| 8 | - <view @click="openOrg" class="u-flex org-device"> | |
| 9 | - <image class="device-image" src="../../../static/org.png"></image> | |
| 10 | - <text class="device-text">摄像头数:{{ cameraTotal }}</text> | |
| 11 | - </view> | |
| 12 | - </view> | |
| 13 | - <view @click="openOrg" class="org-item"> | |
| 14 | - <image class="image" src="../../../static/arrow-right.png"></image> | |
| 15 | - </view> | |
| 16 | - </view> | |
| 17 | - <view style="height: 150rpx;"></view> | |
| 18 | - <!-- 自带分页组件 --> | |
| 19 | - <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 20 | - @up="upCallback"> | |
| 21 | - <view class="camera-container"> | |
| 22 | - <view class="container-item"> | |
| 23 | - <view v-for="(item, index) in list" :key="item.id" class="item"> | |
| 24 | - <video :data-id="item.id" :data-accessMode="item.accessMode" :key="item.id" preload="none" | |
| 25 | - :id="'video' + item.id" class="video" :src="item.videoUrl || commonVideoUrl" controls | |
| 26 | - :title="item.name" x5-video-player-type="h5" x5-video-orientation="portraint" show-mute-btn | |
| 27 | - :poster="item.avatar" @play="playVideo"></video> | |
| 28 | - <view style="width:300rpx" class="bottom-text text-clip"> | |
| 29 | - <text class="text">{{ item.name }}</text> | |
| 30 | - </view> | |
| 31 | - </view> | |
| 32 | - </view> | |
| 33 | - </view> | |
| 34 | - <mescroll-empty v-if="!list.length" /> | |
| 35 | - </mescroll-body> | |
| 36 | - <!-- 自带分页组件 --> | |
| 37 | - <view style="height: 60rpx;"></view> | |
| 38 | - </view> | |
| 39 | -</template> | |
| 40 | - | |
| 41 | -<script> | |
| 42 | - import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 43 | - import api from '@/api/index.js' | |
| 44 | - | |
| 45 | - export default { | |
| 46 | - mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) | |
| 47 | - data() { | |
| 48 | - return { | |
| 49 | - page: { | |
| 50 | - num: 0, | |
| 51 | - size: 10 | |
| 52 | - }, | |
| 53 | - downOption: { | |
| 54 | - auto: true //是否在初始化后,自动执行downCallback; 默认true | |
| 55 | - }, | |
| 56 | - upOption: { | |
| 57 | - auto: false // 不自动加载 | |
| 58 | - }, | |
| 59 | - current: 0, | |
| 60 | - cameraTotal: 0, | |
| 61 | - list: [], | |
| 62 | - ordId: '', | |
| 63 | - commonVideoUrl: 'http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8' | |
| 64 | - }; | |
| 65 | - }, | |
| 66 | - onShow() { | |
| 67 | - if (this.ordId == '') {} else { | |
| 68 | - this.loadData(1, this.ordId); | |
| 69 | - } | |
| 70 | - }, | |
| 71 | - onHide() { | |
| 72 | - this.ordId = ''; | |
| 73 | - this.loadData(1, null); | |
| 74 | - }, | |
| 75 | - onLoad() { | |
| 76 | - // 隐藏原生的tabbar | |
| 77 | - uni.hideTabBar(); | |
| 78 | - }, | |
| 79 | - methods: { | |
| 80 | - /*下拉刷新的回调 */ | |
| 81 | - downCallback() { | |
| 82 | - //联网加载数据 | |
| 83 | - this.page.num = 1; | |
| 84 | - this.loadData(1); | |
| 85 | - }, | |
| 86 | - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 87 | - upCallback() { | |
| 88 | - //联网加载数据 | |
| 89 | - this.page.num += 1; | |
| 90 | - this.loadData(this.page.num); | |
| 91 | - }, | |
| 92 | - async loadData(pageNo, organizationV) { | |
| 93 | - let httpData = { | |
| 94 | - page: pageNo, | |
| 95 | - pageSize: 10, | |
| 96 | - organizationId: organizationV | |
| 97 | - }; | |
| 98 | - const res = await api.homeApi.getCameraApi({ | |
| 99 | - params: httpData, | |
| 100 | - custom: { | |
| 101 | - load: false | |
| 102 | - } | |
| 103 | - }) | |
| 104 | - if (res) { | |
| 105 | - uni.stopPullDownRefresh(); | |
| 106 | - this.mescroll.endByPage(res.items.length, res.total); | |
| 107 | - this.cameraTotal = res.total; | |
| 108 | - if (pageNo == 1) { | |
| 109 | - this.list = res.items; | |
| 110 | - } else { | |
| 111 | - this.list = this.list.concat(res.items); | |
| 112 | - } | |
| 113 | - } | |
| 114 | - }, | |
| 115 | - hideImageUrl(item, index) { | |
| 116 | - this.current = index; | |
| 117 | - }, | |
| 118 | - async playVideo(e) { | |
| 119 | - const { | |
| 120 | - currentTarget: { | |
| 121 | - dataset: { | |
| 122 | - accessmode, | |
| 123 | - id | |
| 124 | - } | |
| 125 | - } = {} | |
| 126 | - } = e | |
| 127 | - const isExistVideoUrl = this.list.find(item => item.id == id).videoUrl | |
| 128 | - if (accessmode === 1 && !isExistVideoUrl) { | |
| 129 | - const res = api.homeApi.byCameraIdGetDetailApi(id) | |
| 130 | - if (res) { | |
| 131 | - const { | |
| 132 | - data: { | |
| 133 | - url | |
| 134 | - } = {} | |
| 135 | - } = res | |
| 136 | - const index = this.list.findIndex(item => item.id === id) | |
| 137 | - if (~index && url) { | |
| 138 | - this.list.splice(index, 1, { | |
| 139 | - ...this.list[index], | |
| 140 | - videoUrl: url | |
| 141 | - }) | |
| 142 | - this.$nextTick(() => { | |
| 143 | - let currentId = 'video' + id; | |
| 144 | - const videoContext = uni.createVideoContext(currentId, this); | |
| 145 | - videoContext.play() | |
| 146 | - }) | |
| 147 | - } | |
| 148 | - } | |
| 149 | - } | |
| 150 | - /** | |
| 151 | - * 点击全屏播放当前视频,暂停其余视频 | |
| 152 | - * 兼容APP和MP端 | |
| 153 | - */ | |
| 154 | - let currentId = 'video' + id; | |
| 155 | - this.videoContent = uni.createVideoContext(currentId, this); | |
| 156 | - this.videoContent.requestFullScreen(); | |
| 157 | - // 获取视频列表 | |
| 158 | - let trailer = this.list; | |
| 159 | - trailer.forEach((item, index) => { | |
| 160 | - if (item.videoUrl != null && item.videoUrl != '') { | |
| 161 | - let temp = 'video' + item.id; | |
| 162 | - if (temp != currentId) { | |
| 163 | - //暂停不是当前的视频 | |
| 164 | - uni.createVideoContext(temp, this).pause(); | |
| 165 | - } | |
| 166 | - } | |
| 167 | - }); | |
| 168 | - }, | |
| 169 | - openOrg() { | |
| 170 | - uni.navigateTo({ | |
| 171 | - url: './org/org' | |
| 172 | - }); | |
| 173 | - } | |
| 174 | - } | |
| 175 | - }; | |
| 176 | -</script> | |
| 177 | - | |
| 178 | -<style lang="scss" scoped> | |
| 179 | - @import '../static/camera.scss'; | |
| 180 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="camera-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <header-org @openOrg="openOrg" :total="cameraTotal" :imageSrc="imageSrc"></header-org> | |
| 6 | + <view style="height: 150rpx;"></view> | |
| 7 | + <!-- 自带分页组件 --> | |
| 8 | + <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 9 | + @up="upCallback"> | |
| 10 | + <view class="camera-container"> | |
| 11 | + <view class="container-item"> | |
| 12 | + <view v-for="(item, index) in list" :key="item.id" class="item"> | |
| 13 | + <video :data-id="item.id" :data-accessMode="item.accessMode" :key="item.id" preload="none" | |
| 14 | + :id="'video' + item.id" class="video" :src="item.videoUrl" controls :title="item.name" | |
| 15 | + x5-video-player-type="h5" x5-video-orientation="portraint" show-mute-btn | |
| 16 | + :poster="item.avatar" @play="playVideo"></video> | |
| 17 | + <view class="bottom-text text-clip w-300"> | |
| 18 | + <text class="text">{{ item.name }}</text> | |
| 19 | + </view> | |
| 20 | + </view> | |
| 21 | + </view> | |
| 22 | + </view> | |
| 23 | + <mescroll-empty v-if="!list.length" /> | |
| 24 | + </mescroll-body> | |
| 25 | + <!-- 自带分页组件 --> | |
| 26 | + <view style="height: 60rpx;"></view> | |
| 27 | + </view> | |
| 28 | +</template> | |
| 29 | + | |
| 30 | +<script> | |
| 31 | + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 32 | + import api from '@/api/index.js' | |
| 33 | + import { | |
| 34 | + useNavigateTo | |
| 35 | + } from '@/plugins/utils.js' | |
| 36 | + import headerOrg from '@/components/common/header-org.vue' | |
| 37 | + | |
| 38 | + export default { | |
| 39 | + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) | |
| 40 | + components:{ | |
| 41 | + headerOrg | |
| 42 | + }, | |
| 43 | + data() { | |
| 44 | + return { | |
| 45 | + imageSrc:'/static/org.png', | |
| 46 | + page: { | |
| 47 | + num: 0, | |
| 48 | + size: 10 | |
| 49 | + }, | |
| 50 | + downOption: { | |
| 51 | + auto: true //是否在初始化后,自动执行downCallback; 默认true | |
| 52 | + }, | |
| 53 | + upOption: { | |
| 54 | + auto: false // 不自动加载 | |
| 55 | + }, | |
| 56 | + current: 0, | |
| 57 | + cameraTotal: 0, | |
| 58 | + list: [], | |
| 59 | + ordId: '', | |
| 60 | + }; | |
| 61 | + }, | |
| 62 | + onShow() { | |
| 63 | + if (this.ordId) { | |
| 64 | + this.loadData(1, this.ordId); | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + onHide() { | |
| 68 | + this.ordId = ''; | |
| 69 | + }, | |
| 70 | + onLoad() { | |
| 71 | + // 隐藏原生的tabbar | |
| 72 | + uni.hideTabBar(); | |
| 73 | + }, | |
| 74 | + methods: { | |
| 75 | + /*下拉刷新的回调 */ | |
| 76 | + downCallback() { | |
| 77 | + //联网加载数据 | |
| 78 | + this.page.num = 1; | |
| 79 | + this.loadData(1); | |
| 80 | + }, | |
| 81 | + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 82 | + upCallback() { | |
| 83 | + //联网加载数据 | |
| 84 | + this.page.num += 1; | |
| 85 | + this.loadData(this.page.num); | |
| 86 | + }, | |
| 87 | + async loadData(pageNo, organizationId) { | |
| 88 | + let httpData = { | |
| 89 | + page: pageNo, | |
| 90 | + pageSize: 10, | |
| 91 | + organizationId | |
| 92 | + }; | |
| 93 | + const res = await api.homeApi.getCameraApi({ | |
| 94 | + params: httpData, | |
| 95 | + custom: { | |
| 96 | + load: false | |
| 97 | + } | |
| 98 | + }) | |
| 99 | + if (res) { | |
| 100 | + uni.stopPullDownRefresh(); | |
| 101 | + this.mescroll.endByPage(res.items.length, res.total); | |
| 102 | + this.cameraTotal = res.total; | |
| 103 | + if (pageNo == 1) { | |
| 104 | + this.list = res.items; | |
| 105 | + } else { | |
| 106 | + this.list = this.list.concat(res.items); | |
| 107 | + } | |
| 108 | + } | |
| 109 | + }, | |
| 110 | + //播放视频 | |
| 111 | + async playVideo(e) { | |
| 112 | + const {currentTarget: {dataset: {accessmode,id}} = {}} = e | |
| 113 | + const isExistVideoUrl = this.list.find(item => item.id == id).videoUrl | |
| 114 | + if (accessmode === 1 && !isExistVideoUrl) { | |
| 115 | + const res = api.homeApi.byCameraIdGetDetailApi(id) | |
| 116 | + if (res) { | |
| 117 | + const {data: {url} = {}} = res | |
| 118 | + const index = this.list.findIndex(item => item.id === id) | |
| 119 | + if (~index && url) { | |
| 120 | + this.list.splice(index, 1, { | |
| 121 | + ...this.list[index], | |
| 122 | + videoUrl: url | |
| 123 | + }) | |
| 124 | + this.$nextTick(() => { | |
| 125 | + let currentId = 'video' + id; | |
| 126 | + const videoContext = uni.createVideoContext(currentId, this); | |
| 127 | + videoContext.play() | |
| 128 | + }) | |
| 129 | + } | |
| 130 | + } | |
| 131 | + } | |
| 132 | + /** | |
| 133 | + * 点击全屏播放当前视频,暂停其余视频 | |
| 134 | + * 兼容APP和MP端 | |
| 135 | + */ | |
| 136 | + let currentId = 'video' + id; | |
| 137 | + this.videoContent = uni.createVideoContext(currentId, this); | |
| 138 | + this.videoContent.requestFullScreen(); | |
| 139 | + // 获取视频列表 | |
| 140 | + let trailer = this.list; | |
| 141 | + trailer.forEach((item, index) => { | |
| 142 | + if (item.videoUrl != null && item.videoUrl != '') { | |
| 143 | + let temp = 'video' + item.id; | |
| 144 | + if (temp != currentId) { | |
| 145 | + //暂停不是当前的视频 | |
| 146 | + uni.createVideoContext(temp, this).pause(); | |
| 147 | + } | |
| 148 | + } | |
| 149 | + }); | |
| 150 | + }, | |
| 151 | + openOrg() { | |
| 152 | + useNavigateTo('/pages/organization/organization') | |
| 153 | + } | |
| 154 | + } | |
| 155 | + }; | |
| 156 | +</script> | |
| 157 | + | |
| 158 | +<style lang="scss" scoped> | |
| 159 | + @import '../../static/camera.scss'; | |
| 160 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/index/components/configuration/configuration-detail.vue
renamed from
pages/index/configuration/configurationDetail.vue
| 1 | -<template> | |
| 2 | - <view class="content"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <web-view :src="showConfiguration" bindload="bindload" binderror="binderror"></web-view> | |
| 6 | - </view> | |
| 7 | -</template> | |
| 8 | - | |
| 9 | -<script> | |
| 10 | - export default { | |
| 11 | - data() { | |
| 12 | - return { | |
| 13 | - showConfiguration: '', | |
| 14 | - defauleConfigImage: 'https://dev.thingskit.com', | |
| 15 | - params: '' | |
| 16 | - }; | |
| 17 | - }, | |
| 18 | - onLoad(e) { | |
| 19 | - uni.setStorageSync('getConfiguration', { | |
| 20 | - isConfiguration: true | |
| 21 | - }); | |
| 22 | - if (e.configId !== null) { | |
| 23 | - this.params = e.configurationHref; | |
| 24 | - this.requestUrl(this.params); | |
| 25 | - } | |
| 26 | - // 隐藏原生的tabbar | |
| 27 | - uni.hideTabBar(); | |
| 28 | - }, | |
| 29 | - onShow() { | |
| 30 | - uni.setStorageSync('getConfiguration', { | |
| 31 | - isConfiguration: true | |
| 32 | - }); | |
| 33 | - }, | |
| 34 | - onUnload() { | |
| 35 | - uni.setStorageSync('getConfiguration', { | |
| 36 | - isConfiguration: false | |
| 37 | - }); | |
| 38 | - uni.removeStorageSync('config'); | |
| 39 | - }, | |
| 40 | - methods: { | |
| 41 | - // 网页加载成功时候触发此事件 | |
| 42 | - bindload(res) { | |
| 43 | - console.log(res, res.detail); | |
| 44 | - }, | |
| 45 | - // 网页加载失败的时候触发此事件 | |
| 46 | - binderror(err) { | |
| 47 | - console.log(err, err.detail); | |
| 48 | - }, | |
| 49 | - async requestUrl(e) { | |
| 50 | - const httpData = { | |
| 51 | - configurationId: e, | |
| 52 | - lightbox: 1 | |
| 53 | - }; | |
| 54 | - const getUrl = await uni.$u.http.get('/', { | |
| 55 | - params: httpData, | |
| 56 | - custom: { | |
| 57 | - load: false | |
| 58 | - } | |
| 59 | - }); | |
| 60 | - const pathUrl = uni.getStorageSync('config'); | |
| 61 | - const userInfo = uni.getStorageSync('userInfo') | |
| 62 | - console.log(this.params) | |
| 63 | - this.showConfiguration = this.params | |
| 64 | - } | |
| 65 | - } | |
| 66 | - }; | |
| 67 | -</script> | |
| 68 | - | |
| 69 | -<style lang="scss" scoped> | |
| 70 | - .content { | |
| 71 | - background: #f8f9fa; | |
| 72 | - min-height: 100vh; | |
| 73 | - } | |
| 74 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="configuation-detail-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <web-view :src="showConfiguration"></web-view> | |
| 6 | + </view> | |
| 7 | +</template> | |
| 8 | + | |
| 9 | +<script> | |
| 10 | + export default { | |
| 11 | + data() { | |
| 12 | + return { | |
| 13 | + showConfiguration: '', | |
| 14 | + defauleConfigImage: 'https://dev.thingskit.com', | |
| 15 | + params: '' | |
| 16 | + }; | |
| 17 | + }, | |
| 18 | + onLoad(e) { | |
| 19 | + uni.setStorageSync('getConfiguration', { | |
| 20 | + isConfiguration: true | |
| 21 | + }); | |
| 22 | + if (e.configId !== null) { | |
| 23 | + this.params = e.configurationHref; | |
| 24 | + this.requestUrl(this.params); | |
| 25 | + } | |
| 26 | + // 隐藏原生的tabbar | |
| 27 | + uni.hideTabBar(); | |
| 28 | + }, | |
| 29 | + onShow() { | |
| 30 | + uni.setStorageSync('getConfiguration', { | |
| 31 | + isConfiguration: true | |
| 32 | + }); | |
| 33 | + }, | |
| 34 | + onUnload() { | |
| 35 | + uni.setStorageSync('getConfiguration', { | |
| 36 | + isConfiguration: false | |
| 37 | + }); | |
| 38 | + uni.removeStorageSync('config'); | |
| 39 | + }, | |
| 40 | + methods: { | |
| 41 | + async requestUrl(e) { | |
| 42 | + const httpData = { | |
| 43 | + configurationId: e, | |
| 44 | + lightbox: 1 | |
| 45 | + }; | |
| 46 | + const getUrl = await uni.$u.http.get('/', { | |
| 47 | + params: httpData, | |
| 48 | + custom: { | |
| 49 | + load: false | |
| 50 | + } | |
| 51 | + }); | |
| 52 | + const pathUrl = uni.getStorageSync('config'); | |
| 53 | + const userInfo = uni.getStorageSync('userInfo') | |
| 54 | + this.showConfiguration = this.params | |
| 55 | + } | |
| 56 | + } | |
| 57 | + }; | |
| 58 | +</script> | |
| 59 | + | |
| 60 | +<style lang="scss" scoped> | |
| 61 | + @import '../../static/configuration.scss'; | |
| 62 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/index/components/configuration/configuration.vue
renamed from
pages/index/configuration/configuration.vue
| 1 | -<template> | |
| 2 | - <view class="status-page"> | |
| 3 | - <view style="margin-left:15rpx;background-color: #f8f9fa;position:fixed;top:0rpx;z-index: 99999;"> | |
| 4 | - <view style="height:35rpx;background-color: #f8f9fa;"></view> | |
| 5 | - <view class="u-flex search-top"> | |
| 6 | - <view class="search-main"> | |
| 7 | - <u--input @change="inputChanged" prefixIcon="search" placeholder="请输入组态名称" border="surround" | |
| 8 | - shape="circle"></u--input> | |
| 9 | - </view> | |
| 10 | - </view> | |
| 11 | - </view> | |
| 12 | - <view style="height:35rpx"></view> | |
| 13 | - <!-- 公共组件-每个页面必须引入 --> | |
| 14 | - <public-module></public-module> | |
| 15 | - <!-- 自带分页组件 --> | |
| 16 | - <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 17 | - @up="upCallback"> | |
| 18 | - <view class="configuation-container"> | |
| 19 | - <view class="configuation-item"> | |
| 20 | - <view @click="openConfigDetail(item)" v-for="(item, index) in list" :key="index" class="item"> | |
| 21 | - <image class="image" :src="item.icon || defaultConfigImage"></image> | |
| 22 | - <text class="name">{{ item.name }}</text> | |
| 23 | - </view> | |
| 24 | - </view> | |
| 25 | - </view> | |
| 26 | - <mescroll-empty v-if="!list.length" /> | |
| 27 | - </mescroll-body> | |
| 28 | - <!-- 自带分页组件 --> | |
| 29 | - <view style="height: 60rpx;"></view> | |
| 30 | - </view> | |
| 31 | -</template> | |
| 32 | - | |
| 33 | -<script> | |
| 34 | - import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 35 | - import api from '@/api/index.js' | |
| 36 | - import { | |
| 37 | - createScadaPageLink | |
| 38 | - } from './help'; | |
| 39 | - | |
| 40 | - export default { | |
| 41 | - mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) | |
| 42 | - data() { | |
| 43 | - return { | |
| 44 | - defaultConfigImage: '../../../static/test.png', | |
| 45 | - page: { | |
| 46 | - num: 0, | |
| 47 | - size: 10 | |
| 48 | - }, | |
| 49 | - downOption: { | |
| 50 | - auto: true //是否在初始化后,自动执行downCallback; 默认true | |
| 51 | - }, | |
| 52 | - upOption: { | |
| 53 | - auto: false // 不自动加载 | |
| 54 | - }, | |
| 55 | - list: [] | |
| 56 | - }; | |
| 57 | - }, | |
| 58 | - onLoad() { | |
| 59 | - // 隐藏原生的tabbar | |
| 60 | - uni.hideTabBar(); | |
| 61 | - uni.setStorageSync('getConfiguration', { | |
| 62 | - isConfiguration: false | |
| 63 | - }); | |
| 64 | - }, | |
| 65 | - onUnload() { | |
| 66 | - uni.setStorageSync('getConfiguration', { | |
| 67 | - isConfiguration: false | |
| 68 | - }); | |
| 69 | - uni.removeStorageSync('getConfiguration'); | |
| 70 | - }, | |
| 71 | - methods: { | |
| 72 | - inputChanged(e) { | |
| 73 | - this.page.num = 1; | |
| 74 | - this.loadData(1, e); | |
| 75 | - }, | |
| 76 | - openConfigDetail(e) { | |
| 77 | - const href = createScadaPageLink(e) | |
| 78 | - uni.navigateTo({ | |
| 79 | - url: 'configurationDetail?configurationHref=' + href | |
| 80 | - }); | |
| 81 | - }, | |
| 82 | - /*下拉刷新的回调 */ | |
| 83 | - downCallback() { | |
| 84 | - //联网加载数据 | |
| 85 | - this.page.num = 1; | |
| 86 | - this.loadData(1); | |
| 87 | - }, | |
| 88 | - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 89 | - upCallback() { | |
| 90 | - //联网加载数据 | |
| 91 | - this.page.num += 1; | |
| 92 | - this.loadData(this.page.num); | |
| 93 | - }, | |
| 94 | - async loadData(pageNo, organizationV) { | |
| 95 | - let httpData = { | |
| 96 | - page: pageNo, | |
| 97 | - pageSize: 10, | |
| 98 | - name: organizationV, | |
| 99 | - platform: 'phone' | |
| 100 | - }; | |
| 101 | - const res = await api.homeApi.getConfigurationApi({ | |
| 102 | - params: httpData, | |
| 103 | - custom: { | |
| 104 | - load: false | |
| 105 | - } | |
| 106 | - }) | |
| 107 | - if (res) { | |
| 108 | - uni.stopPullDownRefresh(); | |
| 109 | - this.mescroll.endByPage(res.items.length, res.total); | |
| 110 | - this.cameraTotal = res.total; | |
| 111 | - if (pageNo == 1) { | |
| 112 | - this.list = res.items; | |
| 113 | - } else { | |
| 114 | - this.list = this.list.concat(res.items); | |
| 115 | - } | |
| 116 | - } | |
| 117 | - } | |
| 118 | - } | |
| 119 | - }; | |
| 120 | -</script> | |
| 121 | - | |
| 122 | -<style lang="scss" scoped> | |
| 123 | - @import '../static/configuration.scss'; | |
| 1 | +<template> | |
| 2 | + <view class="configuation-page"> | |
| 3 | + <view class="configuation-header"> | |
| 4 | + <view class="header-gap"></view> | |
| 5 | + <view class="search-top"> | |
| 6 | + <view class="search-main"> | |
| 7 | + <u--input @change="inputChanged" prefixIcon="search" placeholder="请输入组态名称" border="surround" | |
| 8 | + shape="circle"></u--input> | |
| 9 | + </view> | |
| 10 | + </view> | |
| 11 | + </view> | |
| 12 | + <view style="height:35rpx"></view> | |
| 13 | + <!-- 公共组件-每个页面必须引入 --> | |
| 14 | + <public-module></public-module> | |
| 15 | + <!-- 自带分页组件 --> | |
| 16 | + <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 17 | + @up="upCallback"> | |
| 18 | + <view class="configuation-container"> | |
| 19 | + <view class="configuation-item"> | |
| 20 | + <view @click="openConfigDetail(item)" v-for="(item, index) in list" :key="index" class="item"> | |
| 21 | + <image class="image" :src="item.icon || defaultConfigImage"></image> | |
| 22 | + <text class="name">{{ item.name }}</text> | |
| 23 | + </view> | |
| 24 | + </view> | |
| 25 | + </view> | |
| 26 | + <mescroll-empty v-if="!list.length" /> | |
| 27 | + </mescroll-body> | |
| 28 | + <!-- 自带分页组件 --> | |
| 29 | + <view style="height: 60rpx;"></view> | |
| 30 | + </view> | |
| 31 | +</template> | |
| 32 | + | |
| 33 | +<script> | |
| 34 | + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 35 | + import api from '@/api/index.js' | |
| 36 | + import { | |
| 37 | + createScadaPageLink | |
| 38 | + } from './help'; | |
| 39 | + | |
| 40 | + export default { | |
| 41 | + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) | |
| 42 | + data() { | |
| 43 | + return { | |
| 44 | + defaultConfigImage: '../../../../static/test.png', | |
| 45 | + page: { | |
| 46 | + num: 0, | |
| 47 | + size: 10 | |
| 48 | + }, | |
| 49 | + downOption: { | |
| 50 | + auto: true //是否在初始化后,自动执行downCallback; 默认true | |
| 51 | + }, | |
| 52 | + upOption: { | |
| 53 | + auto: false // 不自动加载 | |
| 54 | + }, | |
| 55 | + list: [] | |
| 56 | + }; | |
| 57 | + }, | |
| 58 | + onLoad() { | |
| 59 | + // 隐藏原生的tabbar | |
| 60 | + uni.hideTabBar(); | |
| 61 | + uni.setStorageSync('getConfiguration', { | |
| 62 | + isConfiguration: false | |
| 63 | + }); | |
| 64 | + }, | |
| 65 | + onUnload() { | |
| 66 | + uni.setStorageSync('getConfiguration', { | |
| 67 | + isConfiguration: false | |
| 68 | + }); | |
| 69 | + uni.removeStorageSync('getConfiguration'); | |
| 70 | + }, | |
| 71 | + methods: { | |
| 72 | + inputChanged(e) { | |
| 73 | + this.page.num = 1; | |
| 74 | + this.loadData(1, e); | |
| 75 | + }, | |
| 76 | + openConfigDetail(e) { | |
| 77 | + const href = createScadaPageLink(e) | |
| 78 | + uni.navigateTo({ | |
| 79 | + url: 'configuration-detail?configurationHref=' + href | |
| 80 | + }); | |
| 81 | + }, | |
| 82 | + /*下拉刷新的回调 */ | |
| 83 | + downCallback() { | |
| 84 | + //联网加载数据 | |
| 85 | + this.page.num = 1; | |
| 86 | + this.loadData(1); | |
| 87 | + }, | |
| 88 | + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ | |
| 89 | + upCallback() { | |
| 90 | + //联网加载数据 | |
| 91 | + this.page.num += 1; | |
| 92 | + this.loadData(this.page.num); | |
| 93 | + }, | |
| 94 | + async loadData(pageNo, organizationV) { | |
| 95 | + let httpData = { | |
| 96 | + page: pageNo, | |
| 97 | + pageSize: 10, | |
| 98 | + name: organizationV, | |
| 99 | + platform: 'phone' | |
| 100 | + }; | |
| 101 | + const res = await api.homeApi.getConfigurationApi({ | |
| 102 | + params: httpData, | |
| 103 | + custom: { | |
| 104 | + load: false | |
| 105 | + } | |
| 106 | + }) | |
| 107 | + if (res) { | |
| 108 | + uni.stopPullDownRefresh(); | |
| 109 | + this.mescroll.endByPage(res.items.length, res.total); | |
| 110 | + this.cameraTotal = res.total; | |
| 111 | + if (pageNo == 1) { | |
| 112 | + this.list = res.items; | |
| 113 | + } else { | |
| 114 | + this.list = this.list.concat(res.items); | |
| 115 | + } | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + }; | |
| 120 | +</script> | |
| 121 | + | |
| 122 | +<style lang="scss" scoped> | |
| 123 | + @import '../../static/configuration.scss'; | |
| 124 | 124 | </style> |
| \ No newline at end of file | ... | ... |
pages/index/components/configuration/help.js
renamed from
pages/index/configuration/help.js
| 1 | -import config from '../../../config/baseUrl.js' | |
| 2 | -import { | |
| 3 | - atob, | |
| 4 | - btoa | |
| 5 | -} from './weapp.atob.js' | |
| 6 | -const getRandomString = () => Number(Math.random().toString().substring(2)).toString(36); | |
| 7 | - | |
| 8 | -export const ScadaModeEnum = { | |
| 9 | - PRIVATE_VIEW: 'PRIVATE_VIEW', | |
| 10 | - PUBLIC_VIEW: 'PUBLIC_VIEW', | |
| 11 | -} | |
| 12 | - | |
| 13 | -export const encode = (record) => { | |
| 14 | - let hash = JSON.stringify(record); | |
| 15 | - const mixinString = getRandomString() | |
| 16 | - .slice(0, 10) | |
| 17 | - .padEnd(10, getRandomString()) | |
| 18 | - .split('') | |
| 19 | - .map((item) => (Math.random() > 0.5 ? item.toUpperCase() : item)) | |
| 20 | - .join(''); | |
| 21 | - hash = btoa(hash); | |
| 22 | - hash = hash.substring(0, 6) + mixinString + hash.substring(6); | |
| 23 | - hash = btoa(hash); | |
| 24 | - return hash; | |
| 25 | -}; | |
| 26 | - | |
| 27 | - | |
| 28 | -export const createScadaPageLink = ( | |
| 29 | - record, | |
| 30 | - mode = ScadaModeEnum.PRIVATE_VIEW, | |
| 31 | - open = false | |
| 32 | -) => { | |
| 33 | - const userInfo = uni.getStorageSync('userInfo') | |
| 34 | - const params = { | |
| 35 | - configurationId: record?.id, | |
| 36 | - organizationId: record?.organizationId, | |
| 37 | - mode: record?.viewType === ScadaModeEnum.PRIVATE_VIEW ? 'lightbox' : 'share', | |
| 1 | +import config from '../../../../config/baseUrl.js' | |
| 2 | +import { | |
| 3 | + atob, | |
| 4 | + btoa | |
| 5 | +} from './weapp.atob.js' | |
| 6 | +const getRandomString = () => Number(Math.random().toString().substring(2)).toString(36); | |
| 7 | + | |
| 8 | +export const ScadaModeEnum = { | |
| 9 | + PRIVATE_VIEW: 'PRIVATE_VIEW', | |
| 10 | + PUBLIC_VIEW: 'PUBLIC_VIEW', | |
| 11 | +} | |
| 12 | + | |
| 13 | +export const encode = (record) => { | |
| 14 | + let hash = JSON.stringify(record); | |
| 15 | + const mixinString = getRandomString() | |
| 16 | + .slice(0, 10) | |
| 17 | + .padEnd(10, getRandomString()) | |
| 18 | + .split('') | |
| 19 | + .map((item) => (Math.random() > 0.5 ? item.toUpperCase() : item)) | |
| 20 | + .join(''); | |
| 21 | + hash = btoa(hash); | |
| 22 | + hash = hash.substring(0, 6) + mixinString + hash.substring(6); | |
| 23 | + hash = btoa(hash); | |
| 24 | + return hash; | |
| 25 | +}; | |
| 26 | + | |
| 27 | + | |
| 28 | +export const createScadaPageLink = ( | |
| 29 | + record, | |
| 30 | + mode = ScadaModeEnum.PRIVATE_VIEW, | |
| 31 | + open = false | |
| 32 | +) => { | |
| 33 | + const userInfo = uni.getStorageSync('userInfo') | |
| 34 | + const params = { | |
| 35 | + configurationId: record?.id, | |
| 36 | + organizationId: record?.organizationId, | |
| 37 | + mode: record?.viewType === ScadaModeEnum.PRIVATE_VIEW ? 'lightbox' : 'share', | |
| 38 | 38 | platform: record?.platform, |
| 39 | - userId: userInfo.userId | |
| 40 | - }; | |
| 41 | - | |
| 42 | - if (record?.viewType === ScadaModeEnum.PUBLIC_VIEW) { | |
| 43 | - params.publicId = record.publicId; | |
| 44 | - } | |
| 45 | - | |
| 46 | - const hash = encode(params); | |
| 47 | - | |
| 48 | - const href = `${config.baseDrawioUrl}#${hash}` | |
| 49 | - | |
| 50 | - return href | |
| 39 | + userId: userInfo.userId | |
| 40 | + }; | |
| 41 | + | |
| 42 | + if (record?.viewType === ScadaModeEnum.PUBLIC_VIEW) { | |
| 43 | + params.publicId = record.publicId; | |
| 44 | + } | |
| 45 | + | |
| 46 | + const hash = encode(params); | |
| 47 | + | |
| 48 | + const href = `${config.baseDrawioUrl}#${hash}` | |
| 49 | + | |
| 50 | + return href | |
| 51 | 51 | }; |
| \ No newline at end of file | ... | ... |
pages/index/components/configuration/weapp.atob.js
renamed from
pages/index/configuration/weapp.atob.js
| 1 | -var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
| 2 | -var b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; | |
| 3 | -export const btoa = function(string) { | |
| 4 | - string = String(string); | |
| 5 | - var bitmap, a, b, c, result = "", | |
| 6 | - i = 0, | |
| 7 | - rest = string.length % 3; | |
| 8 | - for (; i < string.length;) { | |
| 9 | - if ((a = string.charCodeAt(i++)) > 255 || | |
| 10 | - (b = string.charCodeAt(i++)) > 255 || | |
| 11 | - (c = string.charCodeAt(i++)) > 255) | |
| 12 | - throw new TypeError( | |
| 13 | - "Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range." | |
| 14 | - ); | |
| 15 | - bitmap = (a << 16) | (b << 8) | c; | |
| 16 | - result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + | |
| 17 | - b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); | |
| 18 | - } | |
| 19 | - return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result; | |
| 20 | -}; | |
| 21 | - | |
| 22 | -export const atob = function(string) { | |
| 23 | - string = String(string).replace(/[\t\n\f\r ]+/g, ""); | |
| 24 | - if (!b64re.test(string)) | |
| 25 | - throw new TypeError( | |
| 26 | - "Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); | |
| 27 | - string += "==".slice(2 - (string.length & 3)); | |
| 28 | - var bitmap, result = "", | |
| 29 | - r1, r2, i = 0; | |
| 30 | - for (; i < string.length;) { | |
| 31 | - bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | | |
| 32 | - (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); | |
| 33 | - result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) : | |
| 34 | - r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) : | |
| 35 | - String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); | |
| 36 | - } | |
| 37 | - return result; | |
| 38 | -}; | |
| 39 | - | |
| 40 | -function b64DecodeUnicode(str) { | |
| 41 | - return decodeURIComponent(exports.weAtob(str).replace(/(.)/g, function(p) { | |
| 42 | - var code = p.charCodeAt(0).toString(16).toUpperCase(); | |
| 43 | - if (code.length < 2) { | |
| 44 | - code = "0" + code; | |
| 45 | - } | |
| 46 | - return "%" + code; | |
| 47 | - })); | |
| 48 | -} | |
| 49 | - | |
| 50 | -function base64_url_decode(str) { | |
| 51 | - var output = str.replace(/-/g, "+").replace(/_/g, "/"); | |
| 52 | - switch (output.length % 4) { | |
| 53 | - case 0: | |
| 54 | - break; | |
| 55 | - case 2: | |
| 56 | - output += "=="; | |
| 57 | - break; | |
| 58 | - case 3: | |
| 59 | - output += "="; | |
| 60 | - break; | |
| 61 | - default: | |
| 62 | - throw "Illegal base64url string!"; | |
| 63 | - } | |
| 64 | - try { | |
| 65 | - return b64DecodeUnicode(output); | |
| 66 | - } catch (err) { | |
| 67 | - return exports.weAtob(output); | |
| 68 | - } | |
| 69 | -} | |
| 70 | - | |
| 71 | -function weappJwtDecode(token, options) { | |
| 72 | - if (typeof token !== "string") { | |
| 73 | - throw ("Invalid token specified"); | |
| 74 | - } | |
| 75 | - options = options || {}; | |
| 76 | - var pos = options.header === true ? 0 : 1; | |
| 77 | - try { | |
| 78 | - return JSON.parse(base64_url_decode(token.split(".")[pos])); | |
| 79 | - } catch (e) { | |
| 80 | - throw ("Invalid token specified: " + e.message); | |
| 81 | - } | |
| 1 | +var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
| 2 | +var b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; | |
| 3 | +export const btoa = function(string) { | |
| 4 | + string = String(string); | |
| 5 | + var bitmap, a, b, c, result = "", | |
| 6 | + i = 0, | |
| 7 | + rest = string.length % 3; | |
| 8 | + for (; i < string.length;) { | |
| 9 | + if ((a = string.charCodeAt(i++)) > 255 || | |
| 10 | + (b = string.charCodeAt(i++)) > 255 || | |
| 11 | + (c = string.charCodeAt(i++)) > 255) | |
| 12 | + throw new TypeError( | |
| 13 | + "Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range." | |
| 14 | + ); | |
| 15 | + bitmap = (a << 16) | (b << 8) | c; | |
| 16 | + result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + | |
| 17 | + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); | |
| 18 | + } | |
| 19 | + return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result; | |
| 20 | +}; | |
| 21 | + | |
| 22 | +export const atob = function(string) { | |
| 23 | + string = String(string).replace(/[\t\n\f\r ]+/g, ""); | |
| 24 | + if (!b64re.test(string)) | |
| 25 | + throw new TypeError( | |
| 26 | + "Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); | |
| 27 | + string += "==".slice(2 - (string.length & 3)); | |
| 28 | + var bitmap, result = "", | |
| 29 | + r1, r2, i = 0; | |
| 30 | + for (; i < string.length;) { | |
| 31 | + bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | | |
| 32 | + (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); | |
| 33 | + result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) : | |
| 34 | + r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) : | |
| 35 | + String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); | |
| 36 | + } | |
| 37 | + return result; | |
| 38 | +}; | |
| 39 | + | |
| 40 | +function b64DecodeUnicode(str) { | |
| 41 | + return decodeURIComponent(exports.weAtob(str).replace(/(.)/g, function(p) { | |
| 42 | + var code = p.charCodeAt(0).toString(16).toUpperCase(); | |
| 43 | + if (code.length < 2) { | |
| 44 | + code = "0" + code; | |
| 45 | + } | |
| 46 | + return "%" + code; | |
| 47 | + })); | |
| 48 | +} | |
| 49 | + | |
| 50 | +function base64_url_decode(str) { | |
| 51 | + var output = str.replace(/-/g, "+").replace(/_/g, "/"); | |
| 52 | + switch (output.length % 4) { | |
| 53 | + case 0: | |
| 54 | + break; | |
| 55 | + case 2: | |
| 56 | + output += "=="; | |
| 57 | + break; | |
| 58 | + case 3: | |
| 59 | + output += "="; | |
| 60 | + break; | |
| 61 | + default: | |
| 62 | + throw "Illegal base64url string!"; | |
| 63 | + } | |
| 64 | + try { | |
| 65 | + return b64DecodeUnicode(output); | |
| 66 | + } catch (err) { | |
| 67 | + return exports.weAtob(output); | |
| 68 | + } | |
| 69 | +} | |
| 70 | + | |
| 71 | +function weappJwtDecode(token, options) { | |
| 72 | + if (typeof token !== "string") { | |
| 73 | + throw ("Invalid token specified"); | |
| 74 | + } | |
| 75 | + options = options || {}; | |
| 76 | + var pos = options.header === true ? 0 : 1; | |
| 77 | + try { | |
| 78 | + return JSON.parse(base64_url_decode(token.split(".")[pos])); | |
| 79 | + } catch (e) { | |
| 80 | + throw ("Invalid token specified: " + e.message); | |
| 81 | + } | |
| 82 | 82 | } |
| \ No newline at end of file | ... | ... |
pages/index/config/data.js
0 → 100644
| 1 | +const basicGridList = [{ | |
| 2 | + event: 'openCamera', | |
| 3 | + icon: '/static/camer.png', | |
| 4 | + text: '摄像头管理' | |
| 5 | + }, | |
| 6 | + { | |
| 7 | + event: 'openConfiguration', | |
| 8 | + icon: '/static/status.png', | |
| 9 | + text: '组态' | |
| 10 | + }, | |
| 11 | +] | |
| 12 | + | |
| 13 | +const basicStatistics = [{ | |
| 14 | + text: '设备统计', | |
| 15 | + key: 'device', | |
| 16 | + icon: '/static/device-total.png', | |
| 17 | + leftParam: 'ONLINE', | |
| 18 | + centerParam: 'OFFLINE', | |
| 19 | + rightParam: 'INACTIVE', | |
| 20 | + value: { | |
| 21 | + leftValue: 0, | |
| 22 | + centerValue: 0, | |
| 23 | + rightValue: 0 | |
| 24 | + }, | |
| 25 | + label: { | |
| 26 | + leftText: "在线", | |
| 27 | + centerText: "离线", | |
| 28 | + rightText: "待激活" | |
| 29 | + } | |
| 30 | + }, | |
| 31 | + { | |
| 32 | + text: '告警统计', | |
| 33 | + key: 'alarm', | |
| 34 | + icon: '/static/alert.png', | |
| 35 | + leftParam: ['ACTIVE_ACK'], | |
| 36 | + centerParam: 'CLEARED_ACK', | |
| 37 | + rightParam: 'CLEARED_UNACK', | |
| 38 | + value: { | |
| 39 | + leftValue: 0, | |
| 40 | + centerValue: 0, | |
| 41 | + rightValue: 0 | |
| 42 | + }, | |
| 43 | + label: { | |
| 44 | + leftText: "未处理", | |
| 45 | + centerText: "已处理", | |
| 46 | + rightText: "误报" | |
| 47 | + } | |
| 48 | + }, | |
| 49 | +] | |
| 50 | + | |
| 51 | +export { | |
| 52 | + basicGridList, | |
| 53 | + basicStatistics | |
| 54 | +} | |
| \ No newline at end of file | ... | ... |
| 1 | -<template> | |
| 2 | - <view class="index-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view> | |
| 6 | - <!-- 基础统计 --> | |
| 7 | - <view class="basic-sty"> | |
| 8 | - <view class="basic-text"><text class="text text-bold">基础统计</text></view> | |
| 9 | - <view class="basic"> | |
| 10 | - <view class="basic-item"> | |
| 11 | - <view class="item-child-top u-flex"> | |
| 12 | - <image class="item-image" src="../../static/device-total.png"></image> | |
| 13 | - <text class="item-text home-text-muted">设备统计</text> | |
| 14 | - </view> | |
| 15 | - <view class="item-child-bottom u-flex"> | |
| 16 | - <view @click="navigatorDeviceStatus('ONLINE')" class="u-flex sigle-child"> | |
| 17 | - <view class="sigle-text"> | |
| 18 | - <text class="home-text-total">{{ deviceData.onLine }}</text> | |
| 19 | - </view> | |
| 20 | - <view class="sigle-value"><text class="home-text-total-bottom">在线</text></view> | |
| 21 | - </view> | |
| 22 | - <view @click="navigatorDeviceStatus('OFFLINE')" class="u-flex sigle-child"> | |
| 23 | - <view class="sigle-text"> | |
| 24 | - <text class="home-text-total">{{ deviceData.offLine }}</text> | |
| 25 | - </view> | |
| 26 | - <view class="sigle-value"><text class="home-text-total-bottom">离线</text></view> | |
| 27 | - </view> | |
| 28 | - <view @click="navigatorDeviceStatus('INACTIVE')" class="u-flex sigle-child"> | |
| 29 | - <view class="sigle-text"> | |
| 30 | - <text class="home-text-total">{{ deviceData.inActive }}</text> | |
| 31 | - </view> | |
| 32 | - <view class="sigle-value"><text class="home-text-total-bottom">待激活</text></view> | |
| 33 | - </view> | |
| 34 | - </view> | |
| 35 | - </view> | |
| 36 | - <view class="basic-item"> | |
| 37 | - <view class="item-child-top u-flex"> | |
| 38 | - <image class="item-image" src="../../static/alert.png"></image> | |
| 39 | - <text class="item-text home-text-muted">告警统计</text> | |
| 40 | - </view> | |
| 41 | - <view class="item-child-bottom u-flex"> | |
| 42 | - <view @click="navigatorAlarmStatus(['ACTIVE_UNACK'])" | |
| 43 | - class="u-flex sigle-child"> | |
| 44 | - <view class="sigle-text"> | |
| 45 | - <text class="home-text-total">{{ alertData.activedAlarm }}</text> | |
| 46 | - </view> | |
| 47 | - <view class="sigle-value"><text class="home-text-total-bottom">未处理</text></view> | |
| 48 | - </view> | |
| 49 | - <view @click="navigatorAlarmStatus('CLEARED_ACK')" class="u-flex sigle-child"> | |
| 50 | - <view class="sigle-text"> | |
| 51 | - <text class="home-text-total">{{ alertData.clearedAck }}</text> | |
| 52 | - </view> | |
| 53 | - <view class="sigle-value"><text class="home-text-total-bottom">已处理</text></view> | |
| 54 | - </view> | |
| 55 | - <view @click="navigatorAlarmStatus('CLEARED_UNACK')" class="u-flex sigle-child"> | |
| 56 | - <view class="sigle-text"> | |
| 57 | - <text class="home-text-total">{{ alertData.clearedUnack }}</text> | |
| 58 | - </view> | |
| 59 | - <view class="sigle-value"><text class="home-text-total-bottom">误报</text></view> | |
| 60 | - </view> | |
| 61 | - </view> | |
| 62 | - </view> | |
| 63 | - </view> | |
| 64 | - </view> | |
| 65 | - <!-- 基础统计 --> | |
| 66 | - <!-- 四宫格CSS最新网格布局--> | |
| 67 | - <view class="grid-container"> | |
| 68 | - <!-- <view class="grid-item" @click="showToastWip()"> | |
| 69 | - <view class="item-center"> | |
| 70 | - <view class="center"><image class="image" src="../../static/form.png"></image></view> | |
| 71 | - <view class="center-text"><text class="text text-muted">维修工单</text></view> | |
| 72 | - </view> | |
| 73 | - </view> --> | |
| 74 | - <view @click="openCamera" class="grid-item"> | |
| 75 | - <view class="item-center"> | |
| 76 | - <view class="center"> | |
| 77 | - <image class="image" src="../../static/camer.png"></image> | |
| 78 | - </view> | |
| 79 | - <view class="center-text"><text class="text text-muted" style="">摄像头管理</text></view> | |
| 80 | - </view> | |
| 81 | - </view> | |
| 82 | - <!-- <view class="grid-item" @click="showToastWip()"> | |
| 83 | - <view class="item-center"> | |
| 84 | - <view class="center"><image class="image" src="../../static/device.png"></image></view> | |
| 85 | - <view class="center-text"><text class="text text-muted">设备接入</text></view> | |
| 86 | - </view> | |
| 87 | - </view> --> | |
| 88 | - <view @click="openOrgStatus" class="grid-item"> | |
| 89 | - <view class="item-center"> | |
| 90 | - <view class="center"> | |
| 91 | - <image class="image" src="../../static/status.png"></image> | |
| 92 | - </view> | |
| 93 | - <view class="center-text"><text class="text text-muted">组态</text></view> | |
| 94 | - </view> | |
| 95 | - </view> | |
| 96 | - </view> | |
| 97 | - <!-- 四宫格 --> | |
| 98 | - </view> | |
| 99 | - <f-tabbar></f-tabbar> | |
| 100 | - </view> | |
| 101 | -</template> | |
| 102 | - | |
| 103 | -<script> | |
| 104 | - import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 105 | - import { | |
| 106 | - mapActions | |
| 107 | - } from 'vuex'; | |
| 1 | +<template> | |
| 2 | + <view class="index-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view> | |
| 6 | + <!-- 基础统计 --> | |
| 7 | + <view class="basic-statistics"> | |
| 8 | + <view class="basic-text"><text class="text text-bold">基础统计</text></view> | |
| 9 | + <view class="basic"> | |
| 10 | + <view class="basic-item" v-for="(item,index) in basicStatistics" :key="index"> | |
| 11 | + <view class="item-child-top u-flex"> | |
| 12 | + <image class="item-image" :src="item.icon"></image> | |
| 13 | + <text class="item-text home-text-muted">{{item.text}}</text> | |
| 14 | + </view> | |
| 15 | + <view class="item-child-bottom u-flex"> | |
| 16 | + <view @click="navigatorPage(item,item.leftParam)" class="u-flex sigle-child"> | |
| 17 | + <view class="sigle-text"> | |
| 18 | + <text class="home-text-total">{{item.value.leftValue}}</text> | |
| 19 | + </view> | |
| 20 | + <view class="sigle-value"><text | |
| 21 | + class="home-text-total-bottom">{{item.label.leftText}}</text></view> | |
| 22 | + </view> | |
| 23 | + <view @click="navigatorPage(item,item.centerParam)" class="u-flex sigle-child"> | |
| 24 | + <view class="sigle-text"> | |
| 25 | + <text class="home-text-total">{{item.value.centerValue}}</text> | |
| 26 | + </view> | |
| 27 | + <view class="sigle-value"><text | |
| 28 | + class="home-text-total-bottom">{{item.label.centerText}}</text></view> | |
| 29 | + </view> | |
| 30 | + <view @click="navigatorPage(item,item.rightParam)" class="u-flex sigle-child"> | |
| 31 | + <view class="sigle-text"> | |
| 32 | + <text class="home-text-total">{{item.value.rightValue}}</text> | |
| 33 | + </view> | |
| 34 | + <view class="sigle-value"><text | |
| 35 | + class="home-text-total-bottom">{{item.label.rightText}}</text></view> | |
| 36 | + </view> | |
| 37 | + </view> | |
| 38 | + </view> | |
| 39 | + </view> | |
| 40 | + </view> | |
| 41 | + <!-- 网格信息 --> | |
| 42 | + <view class="grid-container"> | |
| 43 | + <view v-for="(item,index) in basicGridList" :key="index" @click="handleEvent(item.event)" | |
| 44 | + class="grid-item"> | |
| 45 | + <view class="item-center"> | |
| 46 | + <view class="center"> | |
| 47 | + <image class="image" :src="item.icon"></image> | |
| 48 | + </view> | |
| 49 | + <view class="center-text"><text class="text text-muted" style="">{{item.text}}</text></view> | |
| 50 | + </view> | |
| 51 | + </view> | |
| 52 | + </view> | |
| 53 | + </view> | |
| 54 | + <f-tabbar></f-tabbar> | |
| 55 | + </view> | |
| 56 | +</template> | |
| 57 | + | |
| 58 | +<script> | |
| 59 | + import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 60 | + import { | |
| 61 | + mapActions | |
| 62 | + } from 'vuex'; | |
| 108 | 63 | import api from '@/api/index.js' |
| 109 | - import { useNavigateTo } from '@/plugins/utils.js' | |
| 110 | - | |
| 111 | - export default { | |
| 112 | - components: { | |
| 113 | - fTabbar | |
| 114 | - }, | |
| 115 | - data() { | |
| 116 | - return { | |
| 117 | - deviceData: { | |
| 118 | - onLine: 0, | |
| 119 | - offLine: 0, | |
| 120 | - inActive: 0 | |
| 121 | - }, | |
| 122 | - alertData: { | |
| 123 | - activedAlarm: 0, | |
| 124 | - clearedAck: 0, | |
| 125 | - clearedUnack: 0 | |
| 126 | - } | |
| 127 | - }; | |
| 128 | - }, | |
| 129 | - onLoad() { | |
| 130 | - // 隐藏原生的tabbar | |
| 131 | - uni.hideTabBar(); | |
| 132 | - if(getApp().getBindNot()){ | |
| 133 | - return | |
| 134 | - } | |
| 135 | - this.getDeviceTotalData(); | |
| 136 | - uni.setStorageSync('getConfiguration', { | |
| 137 | - isConfiguration: false | |
| 138 | - }); | |
| 139 | - uni.removeStorageSync('getConfiguration'); | |
| 64 | + import { | |
| 65 | + useNavigateTo | |
| 66 | + } from '@/plugins/utils.js' | |
| 67 | + import { | |
| 68 | + basicGridList, | |
| 69 | + basicStatistics | |
| 70 | + } from './config/data.js' | |
| 71 | + | |
| 72 | + export default { | |
| 73 | + components: { | |
| 74 | + fTabbar | |
| 75 | + }, | |
| 76 | + data() { | |
| 77 | + return { | |
| 78 | + basicGridList, | |
| 79 | + basicStatistics, | |
| 80 | + }; | |
| 81 | + }, | |
| 82 | + onLoad() { | |
| 83 | + // 隐藏原生的tabbar | |
| 84 | + uni.hideTabBar(); | |
| 85 | + if (getApp().getBindNot()) { | |
| 86 | + return | |
| 87 | + } | |
| 88 | + this.getDeviceTotalData(); | |
| 89 | + uni.setStorageSync('getConfiguration', { | |
| 90 | + isConfiguration: false | |
| 91 | + }); | |
| 92 | + uni.removeStorageSync('getConfiguration'); | |
| 140 | 93 | }, |
| 141 | 94 | onPullDownRefresh() { |
| 142 | 95 | this.getDeviceTotalData(); |
| 143 | - setTimeout(function () { | |
| 96 | + setTimeout(function() { | |
| 144 | 97 | uni.stopPullDownRefresh(); |
| 145 | 98 | uni.$u.toast('下拉刷新成功...'); |
| 146 | - }, 1000); | |
| 147 | - }, | |
| 148 | - methods: { | |
| 149 | - ...mapActions(['updateBadgeTotal']), | |
| 150 | - async getDeviceTotalData() { | |
| 151 | - const res = await api.homeApi.getHomeStatisticsApi() | |
| 99 | + }, 200); | |
| 100 | + }, | |
| 101 | + methods: { | |
| 102 | + ...mapActions(['updateBadgeTotal']), | |
| 103 | + async getDeviceTotalData() { | |
| 104 | + const res = await api.homeApi.getHomeStatisticsApi() | |
| 152 | 105 | if (res) { |
| 153 | - for(let i in this.deviceData) Reflect.set(this.deviceData,i,res.totalDevice[i]) | |
| 154 | - for(let i in this.alertData) Reflect.set(this.alertData,i,res.totalAlarm[i]) | |
| 155 | - //异步实时更新告警徽标数 | |
| 156 | - this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 157 | - } | |
| 158 | - }, | |
| 159 | - showToastWip() { | |
| 160 | - uni.$u.toast('拼命开发中 ...'); | |
| 161 | - }, | |
| 106 | + const { onLine,offLine,inActive } = res.totalDevice | |
| 107 | + const { activedAlarm,clearedAck,clearedUnack } = res.totalAlarm | |
| 108 | + this.basicStatistics.map(item=>{ | |
| 109 | + const { key, value } = item | |
| 110 | + if(key === 'device'){ | |
| 111 | + value.leftValue = onLine | |
| 112 | + value.centerValue =offLine | |
| 113 | + value.rightValue = inActive | |
| 114 | + }else{ | |
| 115 | + value.leftValue = activedAlarm | |
| 116 | + value.centerValue =clearedAck | |
| 117 | + value.rightValue = clearedUnack | |
| 118 | + } | |
| 119 | + }) | |
| 120 | + //异步实时更新告警徽标数 | |
| 121 | + this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 122 | + } | |
| 123 | + }, | |
| 162 | 124 | openCamera() { |
| 163 | - useNavigateTo('camera/camera') | |
| 164 | - }, | |
| 165 | - openOrgStatus() { | |
| 166 | - useNavigateTo('configuration/configuration') | |
| 167 | - }, | |
| 168 | - //告警状态查询 | |
| 169 | - navigatorAlarmStatus(e) { | |
| 170 | - uni.reLaunch({ | |
| 171 | - url: '../alarm/alarm?type=' + JSON.stringify(e) | |
| 172 | - }); | |
| 173 | - }, | |
| 174 | - //设备状态查询 | |
| 175 | - navigatorDeviceStatus(e) { | |
| 176 | - uni.reLaunch({ | |
| 177 | - url: `../device/device?deviceState=${e}` | |
| 178 | - }); | |
| 179 | - } | |
| 180 | - } | |
| 181 | - }; | |
| 182 | -</script> | |
| 183 | - | |
| 184 | -<style lang="scss" scoped> | |
| 185 | - @import './static/index.scss'; | |
| 186 | -</style> | |
| 125 | + useNavigateTo('components/camera/camera') | |
| 126 | + }, | |
| 127 | + openConfiguration() { | |
| 128 | + useNavigateTo('components/configuration/configuration') | |
| 129 | + }, | |
| 130 | + handleEvent(event) { | |
| 131 | + if (event === 'openCamera') this.openCamera() | |
| 132 | + else { | |
| 133 | + this.openConfiguration() | |
| 134 | + } | |
| 135 | + }, | |
| 136 | + navigatorPage(item, type) { | |
| 137 | + const { | |
| 138 | + text | |
| 139 | + } = item | |
| 140 | + if (text === '设备统计') this.navigatorDeviceStatus(type) | |
| 141 | + else { | |
| 142 | + this.navigatorAlarmStatus(type) | |
| 143 | + } | |
| 144 | + }, | |
| 145 | + //告警状态查询 | |
| 146 | + navigatorAlarmStatus(e) { | |
| 147 | + uni.reLaunch({ | |
| 148 | + url: '../alarm/alarm?type=' + JSON.stringify(e) | |
| 149 | + }); | |
| 150 | + }, | |
| 151 | + //设备状态查询 | |
| 152 | + navigatorDeviceStatus(e) { | |
| 153 | + uni.reLaunch({ | |
| 154 | + url: '../device/device?deviceState=' + JSON.stringify(e) | |
| 155 | + }); | |
| 156 | + } | |
| 157 | + } | |
| 158 | + }; | |
| 159 | +</script> | |
| 160 | + | |
| 161 | +<style lang="scss" scoped> | |
| 162 | + @import './static/index.scss'; | |
| 163 | +</style> | |
| \ No newline at end of file | ... | ... |
| 1 | 1 | <template> |
| 2 | - <view class="container"> | |
| 3 | - <view class="container-box"> | |
| 4 | - <image :src="mpOwnConfig.logo"></image> | |
| 2 | + <view class="splash-container"> | |
| 3 | + <view class="splash-container-box"> | |
| 4 | + <image v-if="initConfig.logo" :src="initConfig.logo"></image> | |
| 5 | + <image v-else :src="staticLogo"></image> | |
| 5 | 6 | <text class="splash-text-muted">连接世界 创造价值</text> |
| 6 | 7 | </view> |
| 7 | 8 | </view> |
| ... | ... | @@ -12,12 +13,15 @@ |
| 12 | 13 | mapState |
| 13 | 14 | } from 'vuex'; |
| 14 | 15 | import api from '@/api/index.js' |
| 16 | + import { | |
| 17 | + useReLaunch | |
| 18 | + } from '@/plugins/utils.js' | |
| 15 | 19 | |
| 16 | 20 | export default { |
| 17 | 21 | data() { |
| 18 | 22 | return { |
| 19 | - staticLogo: '../../static/logo.png', | |
| 20 | - mpOwnConfig: {} | |
| 23 | + staticLogo: '/static/logo.png', | |
| 24 | + initConfig: {} | |
| 21 | 25 | }; |
| 22 | 26 | }, |
| 23 | 27 | onLoad() { |
| ... | ... | @@ -29,16 +33,12 @@ |
| 29 | 33 | created() { |
| 30 | 34 | if (!this.userInfo.isToken) { |
| 31 | 35 | setTimeout(() => { |
| 32 | - uni.reLaunch({ | |
| 33 | - url: '/publicLoginSubPage/public/login' | |
| 34 | - }); | |
| 35 | - }, 1500); | |
| 36 | + useReLaunch('/login-subpackage/public/login') | |
| 37 | + }, 1000); | |
| 36 | 38 | } else { |
| 37 | 39 | setTimeout(() => { |
| 38 | - uni.reLaunch({ | |
| 39 | - url: '/pages/index/index' | |
| 40 | - }); | |
| 41 | - }, 1500); | |
| 40 | + useReLaunch('/pages/index/index') | |
| 41 | + }, 1000); | |
| 42 | 42 | } |
| 43 | 43 | }, |
| 44 | 44 | computed: { |
| ... | ... | @@ -47,7 +47,7 @@ |
| 47 | 47 | methods: { |
| 48 | 48 | async getPlateForm() { |
| 49 | 49 | const res = await api.loginApi.getPlateCustomApi() |
| 50 | - this.mpOwnConfig = { | |
| 50 | + this.initConfig = { | |
| 51 | 51 | bg: res.background, |
| 52 | 52 | logo: res.logo ? res.logo : this.staticLogo, |
| 53 | 53 | name: res.name |
| ... | ... | @@ -57,22 +57,7 @@ |
| 57 | 57 | }; |
| 58 | 58 | </script> |
| 59 | 59 | |
| 60 | -<style lang="scss"> | |
| 61 | - .container { | |
| 62 | - width: 100%; | |
| 63 | - height: 100%; | |
| 64 | - margin-top: 300rpx; | |
| 65 | - | |
| 66 | - .container-box { | |
| 67 | - display: flex; | |
| 68 | - align-items: center; | |
| 69 | - justify-content: space-between; | |
| 70 | - flex-direction: column; | |
| 71 | 60 | |
| 72 | - image { | |
| 73 | - width: 100rpx; | |
| 74 | - height: 100rpx; | |
| 75 | - } | |
| 76 | - } | |
| 77 | - } | |
| 78 | -</style> | |
| 61 | +<style lang="scss" scoped> | |
| 62 | + @import './static/splash.scss'; | |
| 63 | +</style> | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -2,54 +2,6 @@ |
| 2 | 2 | min-height: 100vh; |
| 3 | 3 | background-color: #f0f2f5; |
| 4 | 4 | } |
| 5 | -.org-sty { | |
| 6 | - width: 750rpx; | |
| 7 | - height: 150rpx; | |
| 8 | - margin-top: 1rpx; | |
| 9 | - background-color: #fff; | |
| 10 | - display: flex; | |
| 11 | - flex-direction: row; | |
| 12 | - justify-content: space-between; | |
| 13 | - position: fixed; | |
| 14 | - z-index: 999999; | |
| 15 | - top: -1rpx; | |
| 16 | - .org-item { | |
| 17 | - width: 350rpx; | |
| 18 | - height: 200rpx; | |
| 19 | - .org-contact { | |
| 20 | - flex-direction: row; | |
| 21 | - margin-top: 26rpx; | |
| 22 | - margin-left: 15rpx; | |
| 23 | - .text { | |
| 24 | - color: #333333; | |
| 25 | - font-size: 15px; | |
| 26 | - margin-left: 14rpx; | |
| 27 | - } | |
| 28 | - } | |
| 29 | - .org-device { | |
| 30 | - margin-top: 23rpx; | |
| 31 | - margin-left: 15rpx; | |
| 32 | - flex-direction: row; | |
| 33 | - .device-image { | |
| 34 | - margin-left: 14rpx; | |
| 35 | - width: 30rpx; | |
| 36 | - height: 30rpx; | |
| 37 | - } | |
| 38 | - .device-text { | |
| 39 | - margin-left: 10rpx; | |
| 40 | - color: #666666; | |
| 41 | - font-size: 12px; | |
| 42 | - } | |
| 43 | - } | |
| 44 | - .image { | |
| 45 | - width: 6px; | |
| 46 | - height: 10px; | |
| 47 | - float: right; | |
| 48 | - margin-right: 34rpx; | |
| 49 | - margin-top: 37rpx; | |
| 50 | - } | |
| 51 | - } | |
| 52 | -} | |
| 53 | 5 | .camera-item { |
| 54 | 6 | height: 200rpx; |
| 55 | 7 | border: 0.1px solid gray; | ... | ... |
| 1 | -.status-page { | |
| 1 | +.configuation-page { | |
| 2 | 2 | background: #f8f9fa; |
| 3 | 3 | padding: 15rpx 15rpx; |
| 4 | 4 | min-height: 100vh; |
| 5 | - .search-top { | |
| 6 | - justify-content: space-between; | |
| 7 | - flex-direction: row; | |
| 8 | - .search-main { | |
| 9 | - width: 700rpx; | |
| 10 | - margin-top: -34rpx; | |
| 5 | + .configuation-header{ | |
| 6 | + margin-left:15rpx; | |
| 7 | + background-color: #f8f9fa; | |
| 8 | + position:fixed; | |
| 9 | + top:0rpx; | |
| 10 | + z-index: 99999; | |
| 11 | + .header-gap{ | |
| 12 | + height:35rpx; | |
| 13 | + background-color: #f8f9fa; | |
| 14 | + } | |
| 15 | + .search-top { | |
| 16 | + justify-content: space-between; | |
| 17 | + flex-direction: row; | |
| 18 | + .search-main { | |
| 19 | + width: 700rpx; | |
| 20 | + margin-top: -34rpx; | |
| 21 | + } | |
| 11 | 22 | } |
| 12 | 23 | } |
| 24 | + | |
| 13 | 25 | .configuation-container { |
| 14 | 26 | .configuation-item { |
| 15 | 27 | width: 750rpx; |
| ... | ... | @@ -43,3 +55,8 @@ |
| 43 | 55 | } |
| 44 | 56 | } |
| 45 | 57 | } |
| 58 | + | |
| 59 | +.configuation-detail-page { | |
| 60 | + background: #f8f9fa; | |
| 61 | + min-height: 100vh; | |
| 62 | + } | |
| \ No newline at end of file | ... | ... |
pages/index/static/splash.scss
0 → 100644
| 1 | +.splash-container { | |
| 2 | + width: 100%; | |
| 3 | + height: 100%; | |
| 4 | + margin-top: 300rpx; | |
| 5 | + | |
| 6 | + .splash-container-box { | |
| 7 | + display: flex; | |
| 8 | + align-items: center; | |
| 9 | + justify-content: space-between; | |
| 10 | + flex-direction: column; | |
| 11 | + | |
| 12 | + image { | |
| 13 | + width: 100rpx; | |
| 14 | + height: 100rpx; | |
| 15 | + } | |
| 16 | + } | |
| 17 | + } | |
| \ No newline at end of file | ... | ... |
pages/organization/organization.vue
renamed from
pages/alarm/org/org.vue
| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 | |
| 18 | 18 | <script> |
| 19 | 19 | import { transOrgFunc } from '@/config/common.js'; |
| 20 | +import api from '@/api/index.js' | |
| 20 | 21 | |
| 21 | 22 | export default { |
| 22 | 23 | data() { |
| ... | ... | @@ -33,16 +34,12 @@ export default { |
| 33 | 34 | this.loadData(); |
| 34 | 35 | }, |
| 35 | 36 | methods: { |
| 36 | - loadData() { | |
| 37 | - uni.$u.http | |
| 38 | - .get('/yt/organization/me/list') | |
| 39 | - .then(res => { | |
| 40 | - if (res) { | |
| 41 | - const list = transOrgFunc(res); | |
| 42 | - this.tree = list; | |
| 43 | - } | |
| 44 | - }) | |
| 45 | - .catch(e => {}); | |
| 37 | + async loadData() { | |
| 38 | + const res = await api.homeApi.getMeOrgListApi() | |
| 39 | + if (res) { | |
| 40 | + const list = transOrgFunc(res); | |
| 41 | + this.tree = list; | |
| 42 | + } | |
| 46 | 43 | }, |
| 47 | 44 | confirm(val) { |
| 48 | 45 | this.id = val[0].id; | ... | ... |
| 1 | +<template> | |
| 2 | + <view> | |
| 3 | + <u-modal :showConfirmButton="false" :show="show" :title="title"> | |
| 4 | + <view v-if="!bindPhone" class="login-phone"> | |
| 5 | + <view class="form-row"> | |
| 6 | + <u--input shape="circle" class="input" prefixIcon="account-fill" type="text" placeholder="请输入登录账号" | |
| 7 | + v-model="bindAccountForm.appUserKey"></u--input> | |
| 8 | + </view> | |
| 9 | + <view class="form-row item-bind"> | |
| 10 | + <u--input class="input" shape="circle" prefixIcon="lock-fill" suffixIconStyle="color: #909399" | |
| 11 | + type="password" placeholder="请输入登录密码" v-model="bindAccountForm.appUserSecret"></u--input> | |
| 12 | + </view> | |
| 13 | + <view class="u-flex item-phone"> | |
| 14 | + <view class="bind-phone-text" @click="openBindPhone">手机绑定</view> | |
| 15 | + </view> | |
| 16 | + </view> | |
| 17 | + <view v-else class="login-phone"> | |
| 18 | + <view class="form-row"> | |
| 19 | + <u--input shape="circle" class="input" type="text" v-model="bindPhoneForm.appUserKey" | |
| 20 | + placeholder="请输入手机号码" placeholder-style="font-weight:normal;color:#bbbbbb;"></u--input> | |
| 21 | + </view> | |
| 22 | + <view class="form-row row-top"> | |
| 23 | + <u--input shape="circle" class="input" type="text" v-model="bindPhoneForm.appUserSecret" | |
| 24 | + placeholder="请输入验证码" placeholder-style="font-weight:normal;color:#bbbbbb;"></u--input> | |
| 25 | + <view style="color: #377dff" class="verify-code" :class="{ forhidden: readonly }" | |
| 26 | + @click="getVerifyCode"> | |
| 27 | + {{ codeText }} | |
| 28 | + </view> | |
| 29 | + </view> | |
| 30 | + <view class="u-flex item-phone"> | |
| 31 | + <view class="bind-phone-text" @click="openBindAccount">账号绑定</view> | |
| 32 | + </view> | |
| 33 | + </view> | |
| 34 | + <view class="bottom-content"> | |
| 35 | + <view class="u-flex content"> | |
| 36 | + <view class="cancel"> | |
| 37 | + <u-button @click="$emit('cancelAccountModal')" type="info" shape="circle" text="取消"></u-button> | |
| 38 | + </view> | |
| 39 | + <view class="confrim"> | |
| 40 | + <u-button @click="handleConfirm" type="primary" shape="circle" text="确认"></u-button> | |
| 41 | + </view> | |
| 42 | + </view> | |
| 43 | + </view> | |
| 44 | + </u-modal> | |
| 45 | + </view> | |
| 46 | +</template> | |
| 47 | + | |
| 48 | +<script> | |
| 49 | + var clear; | |
| 50 | + import fTabbar from '@/components/module/f-tabbar/f-tabbar'; | |
| 51 | + import { | |
| 52 | + loginPasswordReg, | |
| 53 | + useShowToast | |
| 54 | + } from '@/plugins/utils.js' | |
| 55 | + import api from '@/api/index.js' | |
| 56 | + | |
| 57 | + export default { | |
| 58 | + components: { | |
| 59 | + fTabbar, | |
| 60 | + }, | |
| 61 | + props: { | |
| 62 | + show: { | |
| 63 | + type: Boolean, | |
| 64 | + default: false | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + data() { | |
| 68 | + return { | |
| 69 | + readonly: false, | |
| 70 | + codeText: '获取验证码', | |
| 71 | + bindPhone: false, | |
| 72 | + title: '绑定账号', | |
| 73 | + bindAccountForm: { | |
| 74 | + appUserKey: '', | |
| 75 | + appUserSecret: '' | |
| 76 | + }, | |
| 77 | + bindPhoneForm: { | |
| 78 | + appUserKey: '', | |
| 79 | + appUserSecret: '' | |
| 80 | + }, | |
| 81 | + }; | |
| 82 | + }, | |
| 83 | + onLoad(e) { | |
| 84 | + // 隐藏原生的tabbar | |
| 85 | + uni.hideTabBar(); | |
| 86 | + this.getOpenId = getApp().globalData.openId; | |
| 87 | + }, | |
| 88 | + methods: { | |
| 89 | + resetFunc() { | |
| 90 | + this.bindPhone = false; | |
| 91 | + for (let i in this.bindAccountForm) Reflect.set(this.bindAccountForm, i, "") | |
| 92 | + for (let i in this.bindPhoneForm) Reflect.set(this.bindPhoneForm, i, "") | |
| 93 | + }, | |
| 94 | + async handleBindForm(loginMethod, bindAccountForm, toastText) { | |
| 95 | + const data = { | |
| 96 | + loginMethod, | |
| 97 | + ...bindAccountForm, | |
| 98 | + platformName: 'WECHAT', | |
| 99 | + thirdUserId: this.getOpenId | |
| 100 | + }; | |
| 101 | + const res = await api.loginApi.postThirdLoginApi(data) | |
| 102 | + if (!res) return | |
| 103 | + // 储存登录信息 | |
| 104 | + let tokenInfo = { | |
| 105 | + refreshToken: res.refreshToken, | |
| 106 | + isToken: res.token | |
| 107 | + }; | |
| 108 | + let userInfo = { | |
| 109 | + ...tokenInfo, | |
| 110 | + token: true, //token用于判断是否登录 | |
| 111 | + isThirdLogin: false, | |
| 112 | + isThirdLoginAndNoDind: true | |
| 113 | + }; | |
| 114 | + if (userInfo.token) { | |
| 115 | + this.setUserInfo(userInfo); | |
| 116 | + } | |
| 117 | + uni.$u.toast(toastText); | |
| 118 | + this.saveUserInfo(); | |
| 119 | + this.$emit('cancelAccountModal') | |
| 120 | + }, | |
| 121 | + handleConfirm() { | |
| 122 | + //账号绑定 | |
| 123 | + if (!this.bindPhone) { | |
| 124 | + const validateValue = Object.values(this.bindAccountForm) | |
| 125 | + if (!validateValue[0]) return uni.$u.toast("请输入登录账号~"); | |
| 126 | + if (!validateValue[1]) return uni.$u.toast("请输入登录密码~"); | |
| 127 | + if (!loginPasswordReg.test(validateValue[1])) return useShowModal( | |
| 128 | + "密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~", ) | |
| 129 | + this.handleBindForm('ACCOUNT', this.bindAccountForm, '账号绑定成功~') | |
| 130 | + } else { | |
| 131 | + //手机绑定 | |
| 132 | + const phoneRegular = /^1\d{10}$/; | |
| 133 | + const verifyCodeReg = /^\d{6}$/; | |
| 134 | + const validateValue = Object.values(this.bindPhoneForm) | |
| 135 | + if (!validateValue[0]) return uni.$u.toast("请输入手机号码~"); | |
| 136 | + if (!validateValue[1]) return uni.$u.toast("请输入验证码~"); | |
| 137 | + if (!phoneRegular.test(validateValue[0])) return uni.$u.toast("手机号格式不正确~"); | |
| 138 | + if (!verifyCodeReg.test(validateValue[1])) return uni.$u.toast("验证码格式不正确~"); | |
| 139 | + this.handleBindForm('PHONE', this.bindPhoneForm, '手机绑定成功~') | |
| 140 | + } | |
| 141 | + }, | |
| 142 | + async saveUserInfo() { | |
| 143 | + const userInfoRes = await api.loginApi.setUserInfoApi() | |
| 144 | + const plateInfoRes = await api.loginApi.setPlateInfoApi() | |
| 145 | + Promise.all([userInfoRes, plateInfoRes]).then(res => { | |
| 146 | + this.setUserInfo(res[0]) | |
| 147 | + this.setPlateInfo(res[1]) | |
| 148 | + }) | |
| 149 | + }, | |
| 150 | + openBindPhone() { | |
| 151 | + this.bindPhone = true; | |
| 152 | + }, | |
| 153 | + openBindAccount() { | |
| 154 | + this.bindPhone = false; | |
| 155 | + }, | |
| 156 | + //验证码按钮文字状态 | |
| 157 | + verifyCodeCountDown() { | |
| 158 | + const _this = this; | |
| 159 | + this.readonly = true; | |
| 160 | + this.codeText = '60S后重新获取'; | |
| 161 | + var s = 60; | |
| 162 | + clear = setInterval(() => { | |
| 163 | + s--; | |
| 164 | + _this.codeText = s + 'S后重新获取'; | |
| 165 | + if (s <= 0) { | |
| 166 | + clearInterval(clear); | |
| 167 | + _this.codeText = '获取验证码'; | |
| 168 | + _this.readonly = false; | |
| 169 | + } | |
| 170 | + }, 1000); | |
| 171 | + }, | |
| 172 | + //获取验证码 | |
| 173 | + async getVerifyCode() { | |
| 174 | + const phoneRegular = /^1\d{10}$/; | |
| 175 | + if (this.readonly) useShowToast('验证码已发送~') | |
| 176 | + if (!this.bindPhoneForm.appUserKey) return useShowToast('请输入手机号~') | |
| 177 | + if (!phoneRegular.test(this.bindPhoneForm.appUserKey)) return useShowToast('手机号格式不正确~') | |
| 178 | + await api.loginApi.postCodeApi(this.bindPhoneForm.appUserKey) | |
| 179 | + this.verifyCodeCountDown(); //开始倒计时 | |
| 180 | + }, | |
| 181 | + } | |
| 182 | + }; | |
| 183 | +</script> | |
| 184 | + | |
| 185 | +<style lang="scss" scoped> | |
| 186 | + @import '../static/personal.scss'; | |
| 187 | +</style> | |
| \ No newline at end of file | ... | ... |
| 1 | +<template> | |
| 2 | + <view> | |
| 3 | + <u-popup bgColor="transparent" :overlay="true" :show="show" mode="bottom"> | |
| 4 | + <view class="u-flex logout-main"> | |
| 5 | + <view class="main"><text style="color: #999999">您确定要退出当前账号吗?</text></view> | |
| 6 | + <view @click="$emit('logoutBtn')" class="main"><text style="color: #f95e5a">退出登录</text></view> | |
| 7 | + <view class="cancel-text"><text @click="$emit('closeLogoutPopup')" style="color: #3478f7">取消</text> | |
| 8 | + </view> | |
| 9 | + </view> | |
| 10 | + </u-popup> | |
| 11 | + </view> | |
| 12 | +</template> | |
| 13 | + | |
| 14 | +<script> | |
| 15 | + export default { | |
| 16 | + props: { | |
| 17 | + show: { | |
| 18 | + type: Boolean, | |
| 19 | + default: false | |
| 20 | + } | |
| 21 | + }, | |
| 22 | + } | |
| 23 | +</script> | |
| 24 | + | |
| 25 | +<style lang="scss" scoped> | |
| 26 | + @import '../static/personal.scss'; | |
| 27 | +</style> | |
| \ No newline at end of file | ... | ... |
pages/personal/config/data.js
0 → 100644
| 1 | +const systemList = [{ | |
| 2 | + url: '/sysnotify-subpackage/sys-notify/system-notify', | |
| 3 | + text: '系统通知', | |
| 4 | + leftIcon: '/static/sys-not.png', | |
| 5 | + rightIcon: '/static/arrow-right.png' | |
| 6 | + }, | |
| 7 | + { | |
| 8 | + url: '/feedback-subpackage/feedback/feedback', | |
| 9 | + text: '意见反馈', | |
| 10 | + leftIcon: '/static/find-sugg.png', | |
| 11 | + rightIcon: '/static/arrow-right.png' | |
| 12 | + } | |
| 13 | +] | |
| 14 | +export { | |
| 15 | + systemList | |
| 16 | +} | |
| \ No newline at end of file | ... | ... |
| 1 | 1 | <template> |
| 2 | - <view class="personal"> | |
| 2 | + <view class="personal-page"> | |
| 3 | 3 | <!-- 公共组件-每个页面必须引入 --> |
| 4 | 4 | <public-module></public-module> |
| 5 | - <view class="headBox"> | |
| 6 | - <!-- #ifdef MP || APP-PLUS --> | |
| 7 | - <!-- 登录 --> | |
| 5 | + <view class="header-box"> | |
| 8 | 6 | <view class="u-flex u-p-l-30 u-p-r-20 u-p-t-75 u-p-b-30"> |
| 9 | 7 | <block v-if="userInfo.isToken || userInfo.isThirdLogin"> |
| 10 | - <view @click.top="openPersonalInfo" class="u-m-r-20"> | |
| 11 | - <image class="avatar" mode="aspectFill" | |
| 12 | - :src="userInfo.avatar || thirdObj.avatarUrl || '../../static/logo.png'"></image> | |
| 8 | + <view @click.top="navigatorPersonal" class="u-m-r-20"> | |
| 9 | + <image class="avatar" mode="aspectFill" :src="setHeadImage"></image> | |
| 13 | 10 | </view> |
| 14 | - <view class="u-flex-1" @click.top="openPersonalInfo"> | |
| 11 | + <view class="u-flex-1" @click.top="navigatorPersonal"> | |
| 15 | 12 | <view class="nickName u-flex"> |
| 16 | 13 | <view class="name u-m-r-10" v-if="userInfo.realName || userInfo.nickName"> |
| 17 | - <text | |
| 18 | - style="#FFFFFF;font-size: 18px;">{{ userInfo.realName || userInfo.nickName }}</text> | |
| 14 | + <text class="nick-name">{{ userInfo.realName || userInfo.nickName }}</text> | |
| 19 | 15 | </view> |
| 20 | - <view v-if="userInfo.isThirdLogin" @click.stop="clickAccountFunc" class="detail"><text | |
| 16 | + <view v-if="userInfo.isThirdLogin" @click.stop="openBindAccountModal" class="detail"><text | |
| 21 | 17 | class="text">绑定账号</text></view> |
| 22 | 18 | </view> |
| 23 | - <view style="color: #ffffff; font-size: 14px" v-if="userInfo.phoneNumber"> | |
| 24 | - {{ handlePhoneFunc(userInfo.phoneNumber || '') }}</view> | |
| 19 | + <view class="phone-number" v-if="userInfo.phoneNumber"> | |
| 20 | + {{ handlePhoneFunc(userInfo.phoneNumber || '') }} | |
| 21 | + </view> | |
| 25 | 22 | </view> |
| 26 | 23 | </block> |
| 27 | 24 | <block v-else> |
| 28 | - <view class="u-m-r-20" @click="openLoginFunc"> | |
| 25 | + <view class="u-m-r-20" @click="navigatorLogin"> | |
| 29 | 26 | <view class="avatar u-flex"> |
| 30 | - <image class="avatar" mode="aspectFill" src="../../static/logo.png"></image> | |
| 27 | + <image class="avatar" mode="aspectFill" src="/static/logo.png"></image> | |
| 31 | 28 | </view> |
| 32 | 29 | </view> |
| 33 | 30 | <view class="u-flex-1"> |
| 34 | - <view @click="openLoginFunc" class="u-font-lg click-login login-btn">请点击登录</view> | |
| 31 | + <view @click="navigatorLogin" class="u-font-lg click-login login-btn">请点击登录</view> | |
| 35 | 32 | </view> |
| 36 | 33 | </block> |
| 37 | - <view v-if="userInfo.isToken" @click="openPersonalInfo"> | |
| 34 | + <view v-if="userInfo.isToken" @click="navigatorPersonal"> | |
| 38 | 35 | <u-icon name="arrow-right" color="white" size="13"></u-icon> |
| 39 | 36 | </view> |
| 40 | 37 | </view> |
| 41 | - <!-- 登录 --> | |
| 42 | - <!-- #endif --> | |
| 43 | 38 | </view> |
| 44 | 39 | <view class="u-flex my-nav"> |
| 45 | 40 | <view class="nav-main"> |
| 46 | - <view @click="onTokenJump('/sysNotifySubPage/sysNotifyPage/systemNotify')" class="u-flex nav-link"> | |
| 41 | + <view v-for="(item,index) in systemList" :key="index" @click="onTokenJump(item.url)" class="u-flex nav-link"> | |
| 47 | 42 | <view class="nav-image"> |
| 48 | - <image class="image" src="../../static/sys-not.png"></image> | |
| 43 | + <image class="image" :src="item.leftIcon"></image> | |
| 49 | 44 | </view> |
| 50 | - <view class="nav-center"><text class="text">系统通知</text></view> | |
| 45 | + <view class="nav-center"><text class="text">{{item.text}}</text></view> | |
| 51 | 46 | <view class="nav-right"> |
| 52 | - <image class="image" src="../../static/arrow-right.png"></image> | |
| 53 | - </view> | |
| 54 | - </view> | |
| 55 | - <view @click="onTokenJump('/feedBackSubPage/feedback/feedback')" class="u-flex nav-link"> | |
| 56 | - <view class="nav-image"> | |
| 57 | - <image class="image" src="../../static/find-sugg.png"></image> | |
| 58 | - </view> | |
| 59 | - <view class="nav-center"><text class="text">意见反馈</text></view> | |
| 60 | - <view class="nav-right"> | |
| 61 | - <image class="image" src="../../static/arrow-right.png"></image> | |
| 47 | + <image class="image" :src="item.rightIcon"></image> | |
| 62 | 48 | </view> |
| 63 | 49 | </view> |
| 64 | 50 | </view> |
| 65 | - <view @click="onLoginoutFunc" class="u-flex" style="justify-content: center; width: 600rpx"> | |
| 66 | - <button class="submit" size="default" @click="onLoginoutFunc"><text class="text">退出账号</text></button> | |
| 51 | + <view @click="openLogoutPopup" class="u-flex logout-text"> | |
| 52 | + <button class="submit" size="default" @click="openLogoutPopup"><text class="text">退出账号</text></button> | |
| 67 | 53 | </view> |
| 68 | 54 | </view> |
| 69 | 55 | <!-- 绑定账号 --> |
| 70 | - <view> | |
| 71 | - <u-modal :showConfirmButton="false" :show="show" :title="title"> | |
| 72 | - <view v-if="!bindPhone" class="loginPhone"> | |
| 73 | - <view class="form-row"> | |
| 74 | - <u--input shape="circle" class="input" prefixIcon="account-fill" type="text" placeholder="登录账号" | |
| 75 | - v-model="bindAccountObj.appUserKey"></u--input> | |
| 76 | - </view> | |
| 77 | - <view class="form-row item-bind"> | |
| 78 | - <u--input class="input" shape="circle" prefixIcon="lock-fill" suffixIconStyle="color: #909399" | |
| 79 | - type="password" placeholder="登录密码" v-model="bindAccountObj.appUserSecret"></u--input> | |
| 80 | - </view> | |
| 81 | - <view class="u-flex item-phone"> | |
| 82 | - <view class="phone-hide">手机验证码登录</view> | |
| 83 | - <view class="bind-phone-text" @click="bindPhoneFunc">手机绑定</view> | |
| 84 | - </view> | |
| 85 | - </view> | |
| 86 | - <view v-else class="loginPhone"> | |
| 87 | - <view class="form-row"> | |
| 88 | - <u--input shape="circle" class="input" type="text" v-model="bindPhoneObj.appUserKey" | |
| 89 | - placeholder="请输入手机号码" placeholder-style="font-weight:normal;color:#bbbbbb;"></u--input> | |
| 90 | - </view> | |
| 91 | - <view class="form-row row-top"> | |
| 92 | - <u--input shape="circle" class="input" type="text" v-model="bindPhoneObj.appUserSecret" | |
| 93 | - placeholder="请输入验证码" placeholder-style="font-weight:normal;color:#bbbbbb;"></u--input> | |
| 94 | - <view style="color: #377dff" class="getvcode" :class="{ forhidden: readonly }" | |
| 95 | - @click="getVcode">{{ codeText }}</view> | |
| 96 | - </view> | |
| 97 | - <view class="u-flex item-phone"> | |
| 98 | - <view class="phone-hide">手机验证码登录</view> | |
| 99 | - <view class="bind-phone-text" @click="bindAccountFunc">账号绑定</view> | |
| 100 | - </view> | |
| 101 | - </view> | |
| 102 | - <view class="bottom-content"> | |
| 103 | - <view class="u-flex content"> | |
| 104 | - <view class="cancel"> | |
| 105 | - <u-button @click="show = false" type="info" shape="circle" text="取消"></u-button> | |
| 106 | - </view> | |
| 107 | - <view class="confrim"> | |
| 108 | - <u-button @click="bindConfirm" type="primary" shape="circle" text="确认"></u-button> | |
| 109 | - </view> | |
| 110 | - </view> | |
| 111 | - </view> | |
| 112 | - </u-modal> | |
| 113 | - </view> | |
| 114 | - <!-- 退出登录 --> | |
| 115 | - <view> | |
| 116 | - <u-popup bgColor="transparent" :overlay="true" :show="showLogout" mode="bottom"> | |
| 117 | - <view class="u-flex logout-main"> | |
| 118 | - <view class="main"><text style="color: #999999">确定要退出当前账号?</text></view> | |
| 119 | - <view @click.top="logoutBtn" class="main"><text style="color: #f95e5a">退出登录</text></view> | |
| 120 | - <view class="main1"><text @click.top="closeLogout" style="color: #3478f7">取消</text></view> | |
| 121 | - </view> | |
| 122 | - </u-popup> | |
| 123 | - </view> | |
| 56 | + <bind-account-modal ref="bindAccountRef" :show="showBindAccount" @cancelAccountModal="handleCancelAccountModal" /> | |
| 124 | 57 | <!-- 退出登录 --> |
| 58 | + <logout-account-modal ref="logoutAccountRef" :show="showLogout" @logoutBtn="logoutBtn" @closeLogoutPopup="closeLogoutPopup"/> | |
| 125 | 59 | <f-tabbar></f-tabbar> |
| 126 | 60 | </view> |
| 127 | 61 | </template> |
| 128 | 62 | |
| 129 | 63 | <script> |
| 130 | - var clear; | |
| 131 | - import base from '@/config/baseUrl'; | |
| 132 | 64 | import fTabbar from '@/components/module/f-tabbar/f-tabbar'; |
| 133 | - import fNavbar from '@/components/module/f-navbar/f-navbar'; | |
| 134 | - import { | |
| 135 | - mapState, | |
| 136 | - mapMutations | |
| 137 | - } from 'vuex'; | |
| 138 | - import { loginPasswordReg } from '@/plugins/utils.js' | |
| 65 | + import bindAccountModal from './components/bind-account-modal.vue' | |
| 66 | + import logoutAccountModal from './components/logout-account-modal.vue' | |
| 67 | + import { mapState,mapMutations } from 'vuex'; | |
| 68 | + import { useNavigateTo,useReLaunch,useShowModal } from '@/plugins/utils.js' | |
| 69 | + import { systemList } from './config/data.js' | |
| 139 | 70 | |
| 140 | 71 | export default { |
| 141 | 72 | components: { |
| 142 | 73 | fTabbar, |
| 143 | - fNavbar | |
| 74 | + bindAccountModal, | |
| 75 | + logoutAccountModal, | |
| 144 | 76 | }, |
| 145 | 77 | data() { |
| 146 | 78 | return { |
| 147 | - PrimaryColor: '#0079fe', //主题色 | |
| 79 | + showBindAccount: false, | |
| 148 | 80 | showLogout: false, |
| 149 | - readonly: false, | |
| 150 | - codeText: '获取验证码', | |
| 151 | - tips: '验证码', | |
| 152 | - bindPhone: false, | |
| 153 | - show: false, | |
| 154 | - title: '绑定账号', | |
| 155 | - systemInfo: base.systemInfo, | |
| 156 | - PrimaryButtonColor: '#0079fe', //主题色 | |
| 157 | - bindAccountObj: { | |
| 158 | - appUserKey: '', | |
| 159 | - appUserSecret: '' | |
| 160 | - }, | |
| 161 | - bindPhoneObj: { | |
| 162 | - appUserKey: '', | |
| 163 | - appUserSecret: '' | |
| 164 | - }, | |
| 165 | 81 | thirdObj: {}, |
| 166 | - getOpenId: '', | |
| 167 | - mpOwnConfig: {} | |
| 82 | + systemList, | |
| 168 | 83 | }; |
| 169 | 84 | }, |
| 170 | - mounted() { | |
| 171 | - this.getPlateForm(); | |
| 172 | - }, | |
| 173 | 85 | onLoad(e) { |
| 174 | 86 | // 隐藏原生的tabbar |
| 175 | 87 | uni.hideTabBar(); |
| 176 | - // if (e.obj != null) { | |
| 177 | - // const params = JSON.parse(decodeURIComponent(e.obj)); | |
| 178 | - // // uni.$u.toast('eee', params.avatarUrl); | |
| 179 | - // this.thirdObj = params; | |
| 180 | - // } | |
| 181 | - this.getOpenId = getApp().globalData.openId; | |
| 182 | 88 | }, |
| 183 | 89 | computed: { |
| 184 | - ...mapState(['userInfo', 'plateInfo']) | |
| 90 | + ...mapState(['userInfo', 'plateInfo']), | |
| 91 | + setHeadImage() { | |
| 92 | + return this.userInfo.avatar || this.thirdObj.avatarUrl || '/static/logo.png' | |
| 93 | + } | |
| 185 | 94 | }, |
| 186 | 95 | methods: { |
| 187 | - //获取平台定制信息 | |
| 188 | - getPlateForm() { | |
| 189 | - uni.$u.http.get('/yt/app_design/get').then(res => { | |
| 190 | - if (res) { | |
| 191 | - this.mpOwnConfig = { | |
| 192 | - bg: res.background, | |
| 193 | - logo: res.logo, | |
| 194 | - name: res.name | |
| 195 | - }; | |
| 196 | - } | |
| 197 | - }); | |
| 198 | - }, | |
| 96 | + ...mapMutations(['emptyUserInfo', 'setUserInfo', 'setPlateInfo']), | |
| 199 | 97 | handlePhoneFunc(e) { |
| 200 | - //前三后四位显示 | |
| 98 | + //手机号前三后四位显示 | |
| 201 | 99 | const result = /^(\d{3})\d{4}(\d{4})$/; |
| 202 | 100 | const y = e.toString().replace(result, '$1****$2'); |
| 203 | 101 | return y; |
| 204 | 102 | }, |
| 205 | - ...mapMutations(['emptyUserInfo', 'setUserInfo', 'setPlateInfo']), | |
| 206 | 103 | // 跳转前判断登录 |
| 207 | 104 | onTokenJump(url) { |
| 105 | + if(!url) return | |
| 208 | 106 | this.judgeLogin(() => { |
| 209 | - uni.navigateTo({ | |
| 210 | - url: url | |
| 211 | - }); | |
| 107 | + useNavigateTo(url) | |
| 212 | 108 | }); |
| 213 | 109 | }, |
| 214 | 110 | onJump(url) { |
| 215 | - uni.navigateTo({ | |
| 216 | - url: url | |
| 217 | - }); | |
| 111 | + if(!url) return | |
| 112 | + useNavigateTo(url) | |
| 218 | 113 | }, |
| 219 | - openLoginFunc() { | |
| 220 | - uni.navigateTo({ | |
| 221 | - url: '/publicLoginSubPage/public/login' | |
| 222 | - }); | |
| 114 | + navigatorLogin() { | |
| 115 | + useNavigateTo('/login-subpackage/public/login') | |
| 223 | 116 | }, |
| 224 | - openPersonalInfo() { | |
| 225 | - let obj = { | |
| 117 | + navigatorPersonal() { | |
| 118 | + let data = { | |
| 226 | 119 | data: this.userInfo, |
| 227 | 120 | third: this.thirdObj |
| 228 | 121 | }; |
| 229 | - uni.navigateTo({ | |
| 230 | - url: '/publicLoginSubPage/other/set?data=' + JSON.stringify(obj) | |
| 231 | - }); | |
| 232 | - }, | |
| 233 | - clickAccountFunc() { | |
| 234 | - this.show = true; | |
| 235 | - this.resetFunc(); | |
| 236 | - }, | |
| 237 | - resetFunc() { | |
| 238 | - this.bindPhone = false; | |
| 239 | - this.bindAccountObj = {}; | |
| 240 | - this.bindPhoneObj = {}; | |
| 241 | - }, | |
| 242 | - bindConfirm() { | |
| 243 | - //需要绑定 | |
| 244 | - if (!this.bindPhone) { | |
| 245 | - if (this.bindAccountObj.appUserKey == '' || this.bindAccountObj.appUserKey == undefined) { | |
| 246 | - return uni.$u.toast('请输入登录账号~'); | |
| 247 | - } | |
| 248 | - if (this.bindAccountObj.appUserSecret == '') { | |
| 249 | - uni.showToast({ | |
| 250 | - title: '请输入登录密码~', | |
| 251 | - icon: 'none' | |
| 252 | - }); | |
| 253 | - return; | |
| 254 | - } else if (!loginPasswordReg.test(this.bindAccountObj.appUserSecret)) { | |
| 255 | - uni.showModal({ | |
| 256 | - title: '提示', | |
| 257 | - content: '密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~', | |
| 258 | - showCancel: false | |
| 259 | - }); | |
| 260 | - return; | |
| 261 | - } | |
| 262 | - const postData = { | |
| 263 | - loginMethod: 'ACCOUNT', | |
| 264 | - ...this.bindAccountObj, | |
| 265 | - platformName: 'WECHAT', | |
| 266 | - thirdUserId: this.getOpenId | |
| 267 | - }; | |
| 268 | - uni.$u.http | |
| 269 | - .post('/yt/third/bind', postData) | |
| 270 | - .then(res => { | |
| 271 | - if (res) { | |
| 272 | - this.show = false; | |
| 273 | - // 储存登录信息 | |
| 274 | - let resObj = { | |
| 275 | - refreshToken: res.refreshToken, | |
| 276 | - isToken: res.token | |
| 277 | - }; | |
| 278 | - let userInfo = { | |
| 279 | - ...resObj, | |
| 280 | - token: true, //token用于判断是否登录 | |
| 281 | - isThirdLogin: false, | |
| 282 | - isThirdLoginAndNoDind: true | |
| 283 | - }; | |
| 284 | - if (userInfo.token) { | |
| 285 | - this.setUserInfo(userInfo); | |
| 286 | - } | |
| 287 | - uni.showToast({ | |
| 288 | - title: '账号绑定成功~', | |
| 289 | - icon: 'none' | |
| 290 | - }); | |
| 291 | - this.saveUserInfo(); | |
| 292 | - } | |
| 293 | - }) | |
| 294 | - .catch(e => { | |
| 295 | - let msg = e.message || e.data?.message; | |
| 296 | - // if (msg == undefined) { | |
| 297 | - // msg = ''; | |
| 298 | - // } | |
| 299 | - if (msg) uni.$u.toast(msg); | |
| 300 | - this.show = true; | |
| 301 | - }); | |
| 302 | - } else { | |
| 303 | - const phoneRegular = /^1\d{10}$/; | |
| 304 | - if (this.bindPhoneObj.appUserKey == '') { | |
| 305 | - uni.showToast({ | |
| 306 | - title: '请输入手机号码~', | |
| 307 | - icon: 'none' | |
| 308 | - }); | |
| 309 | - return; | |
| 310 | - } else if (!phoneRegular.test(this.bindPhoneObj.appUserKey)) { | |
| 311 | - uni.showToast({ | |
| 312 | - title: '手机号格式不正确~', | |
| 313 | - icon: 'none' | |
| 314 | - }); | |
| 315 | - return; | |
| 316 | - } | |
| 317 | - if (this.bindPhoneObj.appUserSecret == '') { | |
| 318 | - uni.showToast({ | |
| 319 | - title: '请输入验证码~', | |
| 320 | - icon: 'none' | |
| 321 | - }); | |
| 322 | - return; | |
| 323 | - } else if (!/^\d{6}$/.test(this.bindPhoneObj.appUserSecret)) { | |
| 324 | - uni.showToast({ | |
| 325 | - title: '验证码格式不正确~', | |
| 326 | - icon: 'none' | |
| 327 | - }); | |
| 328 | - return; | |
| 329 | - } | |
| 330 | - const postData = { | |
| 331 | - loginMethod: 'PHONE', | |
| 332 | - ...this.bindPhoneObj, | |
| 333 | - platformName: 'WECHAT', | |
| 334 | - thirdUserId: this.getOpenId | |
| 335 | - }; | |
| 336 | - uni.$u.http | |
| 337 | - .post('/yt/third/bind', postData) | |
| 338 | - .then(res => { | |
| 339 | - this.show = false; | |
| 340 | - // 储存登录信息 | |
| 341 | - let resObj = { | |
| 342 | - refreshToken: res.refreshToken, | |
| 343 | - isToken: res.token | |
| 344 | - }; | |
| 345 | - let userInfo = { | |
| 346 | - ...resObj, | |
| 347 | - token: true, //token用于判断是否登录 | |
| 348 | - isThirdLogin: false, | |
| 349 | - isThirdLoginAndNoDind: true | |
| 350 | - }; | |
| 351 | - if (userInfo.token) { | |
| 352 | - this.setUserInfo(userInfo); | |
| 353 | - } | |
| 354 | - uni.showToast({ | |
| 355 | - title: '手机绑定成功~', | |
| 356 | - icon: 'none' | |
| 357 | - }); | |
| 358 | - this.saveUserInfo(); | |
| 359 | - }) | |
| 360 | - .catch(e => { | |
| 361 | - let msg = e.message || e.data?.message; | |
| 362 | - // msg = ''; | |
| 363 | - // } | |
| 364 | - if (msg) uni.$u.toast(msg); | |
| 365 | - this.show = true; | |
| 366 | - }); | |
| 367 | - } | |
| 122 | + useNavigateTo('/login-subpackage/other/set?data=', data) | |
| 368 | 123 | }, |
| 369 | - saveUserInfo() { | |
| 370 | - //储存个人信息 | |
| 371 | - uni.$u.http.get('/yt/user/me/info').then(res => { | |
| 372 | - if (res) { | |
| 373 | - this.setUserInfo(res); | |
| 374 | - } | |
| 375 | - }); | |
| 376 | - //储存平台信息 | |
| 377 | - uni.$u.http.get('/yt/platform/get').then(res => { | |
| 378 | - if (res) { | |
| 379 | - this.setPlateInfo(res); | |
| 380 | - } | |
| 381 | - }); | |
| 124 | + openBindAccountModal() { | |
| 125 | + this.showBindAccount = true; | |
| 126 | + this.$refs.bindAccountRef.resetFunc() | |
| 382 | 127 | }, |
| 383 | - bindPhoneFunc() { | |
| 384 | - this.bindPhone = true; | |
| 385 | - }, | |
| 386 | - bindAccountFunc() { | |
| 387 | - this.bindPhone = false; | |
| 388 | - }, | |
| 389 | - //验证码按钮文字状态 | |
| 390 | - getCodeState() { | |
| 391 | - const _this = this; | |
| 392 | - this.readonly = true; | |
| 393 | - this.codeText = '60S后重新获取'; | |
| 394 | - var s = 60; | |
| 395 | - clear = setInterval(() => { | |
| 396 | - s--; | |
| 397 | - _this.codeText = s + 'S后重新获取'; | |
| 398 | - if (s <= 0) { | |
| 399 | - clearInterval(clear); | |
| 400 | - _this.codeText = '获取验证码'; | |
| 401 | - _this.readonly = false; | |
| 402 | - } | |
| 403 | - }, 1000); | |
| 404 | - }, | |
| 405 | - //获取验证码 | |
| 406 | - getVcode() { | |
| 407 | - if (this.readonly) { | |
| 408 | - uni.showToast({ | |
| 409 | - title: '验证码已发送~', | |
| 410 | - icon: 'none' | |
| 411 | - }); | |
| 412 | - return; | |
| 413 | - } | |
| 414 | - if (this.bindPhoneObj.appUserKey == '') { | |
| 415 | - uni.showToast({ | |
| 416 | - title: '请输入手机号~', | |
| 417 | - icon: 'none' | |
| 418 | - }); | |
| 419 | - return; | |
| 420 | - } | |
| 421 | - const phoneRegular = /^1\d{10}$/; | |
| 422 | - if (!phoneRegular.test(this.bindPhoneObj.appUserKey)) { | |
| 423 | - uni.showToast({ | |
| 424 | - title: '手机号格式不正确~', | |
| 425 | - icon: 'none' | |
| 426 | - }); | |
| 427 | - return; | |
| 428 | - } | |
| 429 | - let httpData = {}; | |
| 430 | - // 获取验证码接口 | |
| 431 | - uni.$u.http.post(`/yt/noauth/send_login_code/${this.bindPhoneObj.appUserKey}`).then(res => { | |
| 432 | - if (res) { | |
| 433 | - this.getCodeState(); //开始倒计时 | |
| 434 | - } | |
| 435 | - }); | |
| 436 | - }, | |
| 437 | - onLoginoutFunc() { | |
| 128 | + openLogoutPopup() { | |
| 438 | 129 | this.showLogout = true; |
| 439 | 130 | }, |
| 440 | - closeLogout() { | |
| 131 | + closeLogoutPopup() { | |
| 441 | 132 | this.showLogout = false; |
| 442 | 133 | }, |
| 443 | 134 | logoutBtn() { |
| 444 | - let that = this; | |
| 445 | - uni.showModal({ | |
| 446 | - title: '退出登录', | |
| 447 | - content: '你确定退出登录吗?', | |
| 448 | - success(res) { | |
| 449 | - if (res.confirm) { | |
| 450 | - that.emptyUserInfo(); | |
| 451 | - that.showLogout = false; | |
| 452 | - setTimeout(() => { | |
| 453 | - uni.navigateTo({ | |
| 454 | - url: '/publicLoginSubPage/public/login' | |
| 455 | - }); | |
| 456 | - }, 500); | |
| 457 | - } else if (res.cancel) {} | |
| 135 | + const that = this | |
| 136 | + useShowModal('您确定要退出登录吗?', '退出登录', '确定').then(res => { | |
| 137 | + if (res.confirm) { | |
| 138 | + that.emptyUserInfo(); | |
| 139 | + that.showLogout = false; | |
| 140 | + //不能使用navigatorTo,会显示返回按钮 | |
| 141 | + useReLaunch('/login-subpackage/public/login') | |
| 458 | 142 | } |
| 459 | - }); | |
| 143 | + }) | |
| 144 | + }, | |
| 145 | + handleCancelAccountModal() { | |
| 146 | + this.showBindAccount = false; | |
| 460 | 147 | } |
| 461 | 148 | } |
| 462 | 149 | }; |
| ... | ... | @@ -464,4 +151,4 @@ |
| 464 | 151 | |
| 465 | 152 | <style lang="scss" scoped> |
| 466 | 153 | @import './static/personal.scss'; |
| 467 | -</style> | |
| 154 | +</style> | |
| \ No newline at end of file | ... | ... |
| 1 | -.personal { | |
| 1 | +.personal-page { | |
| 2 | 2 | background-color: #ffffff; |
| 3 | 3 | height: 100vh; |
| 4 | 4 | } |
| 5 | -.headBox { | |
| 5 | +.header-box { | |
| 6 | 6 | background: linear-gradient(90deg, #8c9ef2 0%, #5f6ee6 100%); |
| 7 | 7 | border-top: 0.01px solid #f5f5f5; |
| 8 | 8 | height: 250rpx; |
| ... | ... | @@ -51,6 +51,10 @@ |
| 51 | 51 | color: #fff; |
| 52 | 52 | font-weight: bold; |
| 53 | 53 | font-size: 32rpx; |
| 54 | + .nick-name{ | |
| 55 | + color:#FFFFFF; | |
| 56 | + font-size: 18px; | |
| 57 | + } | |
| 54 | 58 | } |
| 55 | 59 | |
| 56 | 60 | .placardVip { |
| ... | ... | @@ -62,7 +66,10 @@ |
| 62 | 66 | border-radius: 4rpx; |
| 63 | 67 | } |
| 64 | 68 | } |
| 65 | - | |
| 69 | + .phone-number{ | |
| 70 | + color: #ffffff; | |
| 71 | + font-size: 14px; | |
| 72 | + } | |
| 66 | 73 | .detail { |
| 67 | 74 | color: #fff; |
| 68 | 75 | font-size: 24rpx; |
| ... | ... | @@ -97,6 +104,10 @@ |
| 97 | 104 | justify-content: space-between; |
| 98 | 105 | height: 147rpx; |
| 99 | 106 | } |
| 107 | + .logout-text{ | |
| 108 | + justify-content: center; | |
| 109 | + width: 600rpx | |
| 110 | + } | |
| 100 | 111 | .submit { |
| 101 | 112 | margin-top: 60rpx; |
| 102 | 113 | background: linear-gradient(90deg, #5dc2fc 0%, #377dff 100%); |
| ... | ... | @@ -169,7 +180,7 @@ |
| 169 | 180 | border: none; |
| 170 | 181 | } |
| 171 | 182 | |
| 172 | -.loginPhone { | |
| 183 | +.login-phone { | |
| 173 | 184 | .form-row { |
| 174 | 185 | position: relative; |
| 175 | 186 | // background: #f7f9ff; |
| ... | ... | @@ -186,7 +197,7 @@ |
| 186 | 197 | font-weight: bold; |
| 187 | 198 | } |
| 188 | 199 | |
| 189 | - .getvcode { | |
| 200 | + .verify-code { | |
| 190 | 201 | font-size: 26rpx; |
| 191 | 202 | height: 50rpx; |
| 192 | 203 | color: #333; |
| ... | ... | @@ -218,11 +229,9 @@ |
| 218 | 229 | height: 80rpx; |
| 219 | 230 | } |
| 220 | 231 | .item-phone { |
| 221 | - flex-direction: row; | |
| 232 | + display: flex; | |
| 233 | + justify-content: center; | |
| 222 | 234 | margin-top: 20rpx; |
| 223 | - .phone-hide { | |
| 224 | - visibility: hidden; | |
| 225 | - } | |
| 226 | 235 | .bind-phone-text { |
| 227 | 236 | color: #0079fe; |
| 228 | 237 | font-size: 14px; |
| ... | ... | @@ -256,7 +265,7 @@ |
| 256 | 265 | text-align: center; |
| 257 | 266 | line-height: 86rpx; |
| 258 | 267 | } |
| 259 | - .main1 { | |
| 268 | + .cancel-text { | |
| 260 | 269 | width: 669rpx; |
| 261 | 270 | height: 100rpx; |
| 262 | 271 | text-align: center; | ... | ... |
| ... | ... | @@ -4,156 +4,281 @@ const DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss"; |
| 4 | 4 | |
| 5 | 5 | /** |
| 6 | 6 | 登录密码正则验证 |
| 7 | - 最短8位,最长16位 | |
| 8 | - 必须包含1个数字 | |
| 9 | - 必须包含1个小写字母 | |
| 10 | - 必须包含1个大写字母 | |
| 7 | + 最短8位,最长16位 | |
| 8 | + 必须包含1个数字 | |
| 9 | + 必须包含1个小写字母 | |
| 10 | + 必须包含1个大写字母 | |
| 11 | 11 | 必须包含1个特殊字符 |
| 12 | 12 | */ |
| 13 | -export const loginPasswordReg =/^.*(?=.{6,16})(?=.*\d)(?=.*[A-Z]{1,})(?=.*[a-z]{1,})(?=.*[_!@#$%^&*?\(\)]).*$/; | |
| 13 | +export const loginPasswordReg = | |
| 14 | + /^.*(?=.{6,16})(?=.*\d)(?=.*[A-Z]{1,})(?=.*[a-z]{1,})(?=.*[_!@#$%^&*?\(\)]).*$/; | |
| 14 | 15 | |
| 15 | 16 | //手机号中间4位为* |
| 16 | -Vue.filter("phone", function (val) { | |
| 17 | - var tel = val; | |
| 18 | - tel = "" + tel; | |
| 19 | - var telShort = tel.replace(tel.substring(3, 7), "****"); | |
| 20 | - return telShort; | |
| 17 | +Vue.filter("phone", function(val) { | |
| 18 | + var tel = val; | |
| 19 | + tel = "" + tel; | |
| 20 | + var telShort = tel.replace(tel.substring(3, 7), "****"); | |
| 21 | + return telShort; | |
| 21 | 22 | }); |
| 22 | 23 | //获取系统信息、判断ipX安全距离 |
| 23 | -export const getTabbarHeight = function () { | |
| 24 | - var systemInfo = uni.getSystemInfoSync(); | |
| 25 | - var data = { | |
| 26 | - ...systemInfo, | |
| 27 | - tabbarH: 50, //tabbar高度--单位px | |
| 28 | - tabbarPaddingB: 0, //tabbar底部安全距离高度--单位px | |
| 29 | - device: systemInfo.system.indexOf("iOS") != -1 ? "iOS" : "Android", //苹果或者安卓设备 | |
| 30 | - }; | |
| 31 | - let modelArr = [ | |
| 32 | - "10,3", | |
| 33 | - "10,6", | |
| 34 | - "X", | |
| 35 | - "XR", | |
| 36 | - "XS", | |
| 37 | - "11", | |
| 38 | - "12", | |
| 39 | - "13", | |
| 40 | - "14", | |
| 41 | - "15", | |
| 42 | - "16", | |
| 43 | - ]; | |
| 44 | - let model = systemInfo.model; | |
| 45 | - model && | |
| 46 | - modelArr.forEach((item) => { | |
| 47 | - //适配iphoneX以上的底部,给tabbar一定高度的padding-bottom | |
| 48 | - if ( | |
| 49 | - model.indexOf(item) != -1 && | |
| 50 | - (model.indexOf("iPhone") != -1 || model.indexOf("iphone") != -1) | |
| 51 | - ) { | |
| 52 | - data.tabbarH = 70; | |
| 53 | - data.tabbarPaddingB = 20; | |
| 54 | - } | |
| 55 | - }); | |
| 56 | - return data; | |
| 24 | +export const getTabbarHeight = function() { | |
| 25 | + var systemInfo = uni.getSystemInfoSync(); | |
| 26 | + var data = { | |
| 27 | + ...systemInfo, | |
| 28 | + tabbarH: 50, //tabbar高度--单位px | |
| 29 | + tabbarPaddingB: 0, //tabbar底部安全距离高度--单位px | |
| 30 | + device: systemInfo.system.indexOf("iOS") != -1 ? "iOS" : "Android", //苹果或者安卓设备 | |
| 31 | + }; | |
| 32 | + let modelArr = [ | |
| 33 | + "10,3", | |
| 34 | + "10,6", | |
| 35 | + "X", | |
| 36 | + "XR", | |
| 37 | + "XS", | |
| 38 | + "11", | |
| 39 | + "12", | |
| 40 | + "13", | |
| 41 | + "14", | |
| 42 | + "15", | |
| 43 | + "16", | |
| 44 | + ]; | |
| 45 | + let model = systemInfo.model; | |
| 46 | + model && | |
| 47 | + modelArr.forEach((item) => { | |
| 48 | + //适配iphoneX以上的底部,给tabbar一定高度的padding-bottom | |
| 49 | + if ( | |
| 50 | + model.indexOf(item) != -1 && | |
| 51 | + (model.indexOf("iPhone") != -1 || model.indexOf("iphone") != -1) | |
| 52 | + ) { | |
| 53 | + data.tabbarH = 70; | |
| 54 | + data.tabbarPaddingB = 20; | |
| 55 | + } | |
| 56 | + }); | |
| 57 | + return data; | |
| 57 | 58 | }; |
| 58 | 59 | |
| 59 | 60 | // px转upx |
| 60 | -export const px2upx = function (n) { | |
| 61 | - return n / (uni.upx2px(n) / n); | |
| 61 | +export const px2upx = function(n) { | |
| 62 | + return n / (uni.upx2px(n) / n); | |
| 62 | 63 | }; |
| 63 | 64 | |
| 64 | 65 | // 小程序获取定位权限判断 |
| 65 | 66 | // isOpenSetting 默认false:不检验授权,true:检验授权后获取地址 |
| 66 | 67 | function getMpLocation(successCallback, errCallback, isOpenSetting) { |
| 67 | - uni.getSetting({ | |
| 68 | - success: (res) => { | |
| 69 | - if (res.authSetting["scope.userLocation"] || !isOpenSetting) { | |
| 70 | - uni.getLocation({ | |
| 71 | - // #ifndef MP-ALIPAY | |
| 72 | - type: "gcj02", | |
| 73 | - // #endif | |
| 74 | - success(res) { | |
| 75 | - console.log("successCallback"); | |
| 76 | - successCallback(res); | |
| 77 | - }, | |
| 78 | - fail(err) { | |
| 79 | - console.log("位置信息错误", err); | |
| 80 | - errCallback("位置信息获取失败"); | |
| 81 | - }, | |
| 82 | - }); | |
| 83 | - } else { | |
| 84 | - errCallback("“位置信息”未授权"); | |
| 85 | - isOpenSetting && | |
| 86 | - uni.showModal({ | |
| 87 | - title: "提示", | |
| 88 | - content: "请先在设置页面打开“位置信息”使用权限", | |
| 89 | - confirmText: "去设置", | |
| 90 | - cancelText: "再逛会", | |
| 91 | - success: (res) => { | |
| 92 | - if (res.confirm) { | |
| 93 | - uni.openSetting(); | |
| 94 | - } | |
| 95 | - }, | |
| 96 | - }); | |
| 97 | - } | |
| 98 | - }, | |
| 99 | - }); | |
| 68 | + uni.getSetting({ | |
| 69 | + success: (res) => { | |
| 70 | + if (res.authSetting["scope.userLocation"] || !isOpenSetting) { | |
| 71 | + uni.getLocation({ | |
| 72 | + // #ifndef MP-ALIPAY | |
| 73 | + type: "gcj02", | |
| 74 | + // #endif | |
| 75 | + success(res) { | |
| 76 | + console.log("successCallback"); | |
| 77 | + successCallback(res); | |
| 78 | + }, | |
| 79 | + fail(err) { | |
| 80 | + console.log("位置信息错误", err); | |
| 81 | + errCallback("位置信息获取失败"); | |
| 82 | + }, | |
| 83 | + }); | |
| 84 | + } else { | |
| 85 | + errCallback("“位置信息”未授权"); | |
| 86 | + isOpenSetting && | |
| 87 | + uni.showModal({ | |
| 88 | + title: "提示", | |
| 89 | + content: "请先在设置页面打开“位置信息”使用权限", | |
| 90 | + confirmText: "去设置", | |
| 91 | + cancelText: "再逛会", | |
| 92 | + success: (res) => { | |
| 93 | + if (res.confirm) { | |
| 94 | + uni.openSetting(); | |
| 95 | + } | |
| 96 | + }, | |
| 97 | + }); | |
| 98 | + } | |
| 99 | + }, | |
| 100 | + }); | |
| 100 | 101 | } |
| 101 | 102 | // 获取地址信息 |
| 102 | 103 | let locationAuthorize = true; |
| 103 | -export const getAppLatLon = function ( | |
| 104 | - successCallback, | |
| 105 | - errCallback, | |
| 106 | - isOpenSetting | |
| 104 | +export const getAppLatLon = function( | |
| 105 | + successCallback, | |
| 106 | + errCallback, | |
| 107 | + isOpenSetting | |
| 107 | 108 | ) { |
| 108 | - const _this = this; | |
| 109 | - // #ifdef MP-WEIXIN | |
| 110 | - if (locationAuthorize && isOpenSetting) { | |
| 111 | - uni.authorize({ | |
| 112 | - scope: "scope.userLocation", | |
| 113 | - success: () => { | |
| 114 | - getMpLocation(successCallback, errCallback, isOpenSetting); | |
| 115 | - locationAuthorize = false; | |
| 116 | - }, | |
| 117 | - fail: () => { | |
| 118 | - locationAuthorize = false; | |
| 119 | - }, | |
| 120 | - }); | |
| 121 | - } else { | |
| 122 | - getMpLocation(successCallback, errCallback, isOpenSetting); | |
| 123 | - } | |
| 124 | - // #endif | |
| 125 | - // #ifdef MP-ALIPAY | |
| 126 | - getMpLocation(successCallback, errCallback, false); | |
| 127 | - // #endif | |
| 128 | - // #ifdef H5 | |
| 129 | - uni.getLocation({ | |
| 130 | - type: "gcj02", | |
| 131 | - success(res) { | |
| 132 | - console.log("successCallback"); | |
| 133 | - successCallback(res); | |
| 134 | - }, | |
| 135 | - fail(err) { | |
| 136 | - console.log("位置信息错误", err); | |
| 137 | - errCallback("位置信息获取失败"); | |
| 138 | - }, | |
| 139 | - }); | |
| 140 | - // #endif | |
| 109 | + const _this = this; | |
| 110 | + // #ifdef MP-WEIXIN | |
| 111 | + if (locationAuthorize && isOpenSetting) { | |
| 112 | + uni.authorize({ | |
| 113 | + scope: "scope.userLocation", | |
| 114 | + success: () => { | |
| 115 | + getMpLocation(successCallback, errCallback, isOpenSetting); | |
| 116 | + locationAuthorize = false; | |
| 117 | + }, | |
| 118 | + fail: () => { | |
| 119 | + locationAuthorize = false; | |
| 120 | + }, | |
| 121 | + }); | |
| 122 | + } else { | |
| 123 | + getMpLocation(successCallback, errCallback, isOpenSetting); | |
| 124 | + } | |
| 125 | + // #endif | |
| 126 | + // #ifdef MP-ALIPAY | |
| 127 | + getMpLocation(successCallback, errCallback, false); | |
| 128 | + // #endif | |
| 129 | + // #ifdef H5 | |
| 130 | + uni.getLocation({ | |
| 131 | + type: "gcj02", | |
| 132 | + success(res) { | |
| 133 | + console.log("successCallback"); | |
| 134 | + successCallback(res); | |
| 135 | + }, | |
| 136 | + fail(err) { | |
| 137 | + console.log("位置信息错误", err); | |
| 138 | + errCallback("位置信息获取失败"); | |
| 139 | + }, | |
| 140 | + }); | |
| 141 | + // #endif | |
| 141 | 142 | }; |
| 142 | 143 | |
| 143 | 144 | export function formatToDate(date = undefined, format = DATE_TIME_FORMAT) { |
| 144 | - return moment(date).format(format); | |
| 145 | + return moment(date).format(format); | |
| 145 | 146 | } |
| 146 | 147 | |
| 147 | 148 | //封装uniapp跳转 navigateTo |
| 148 | -export const useNavigateTo=(path,param)=>{ | |
| 149 | - if (!path) return | |
| 150 | - if(param){ | |
| 149 | +export const useNavigateTo = (path, param) => { | |
| 150 | + if (!path) return; | |
| 151 | + if (param) { | |
| 151 | 152 | uni.navigateTo({ |
| 152 | - url: path + encodeURIComponent(JSON.stringify(param)) | |
| 153 | + url: path + encodeURIComponent(JSON.stringify(param)), | |
| 153 | 154 | }); |
| 154 | - }else{ | |
| 155 | + } else { | |
| 155 | 156 | uni.navigateTo({ |
| 156 | - url:path | |
| 157 | + url: path, | |
| 158 | + }); | |
| 159 | + } | |
| 160 | +}; | |
| 161 | + | |
| 162 | +//封装uniapp跳转 reLaunch | |
| 163 | +export const useReLaunch = (path, param) => { | |
| 164 | + if (!path) return; | |
| 165 | + if (param) { | |
| 166 | + uni.reLaunch({ | |
| 167 | + url: path + encodeURIComponent(JSON.stringify(param)), | |
| 168 | + }); | |
| 169 | + } else { | |
| 170 | + uni.reLaunch({ | |
| 171 | + url: path, | |
| 172 | + }); | |
| 173 | + } | |
| 174 | +}; | |
| 175 | + | |
| 176 | +//封装uniapp showToast | |
| 177 | +export const useShowToast = (title, duration = 500, mask = false) => { | |
| 178 | + return new Promise((resolve, reject) => { | |
| 179 | + uni.showToast({ | |
| 180 | + title: title, | |
| 181 | + icon: "none", | |
| 182 | + duration, | |
| 183 | + mask, | |
| 184 | + success: (res) => { | |
| 185 | + resolve(res); | |
| 186 | + }, | |
| 187 | + fail: (err) => { | |
| 188 | + reject(err); | |
| 189 | + }, | |
| 190 | + }); | |
| 191 | + }); | |
| 192 | +}; | |
| 193 | + | |
| 194 | +//封装uniapp showModal | |
| 195 | +export const useShowModal = (content, title = "提示", confirmText = "确定") => { | |
| 196 | + return new Promise((resolve, reject) => { | |
| 197 | + uni.showModal({ | |
| 198 | + title, | |
| 199 | + content: content, | |
| 200 | + confirmText, | |
| 201 | + success: (res) => { | |
| 202 | + resolve(res); | |
| 203 | + }, | |
| 204 | + fail: (err) => { | |
| 205 | + reject(err); | |
| 206 | + }, | |
| 207 | + }); | |
| 208 | + }); | |
| 209 | +}; | |
| 210 | + | |
| 211 | +//封装uniapp uni.uploadFile | |
| 212 | +export const useUploadFile = ( | |
| 213 | + url, | |
| 214 | + filePath, | |
| 215 | + name = "file", | |
| 216 | + formData, | |
| 217 | + header | |
| 218 | +) => { | |
| 219 | + return new Promise(function(resolve, reject) { | |
| 220 | + uni.uploadFile({ | |
| 221 | + url, //请求接口地址 | |
| 222 | + filePath, //文件地址 | |
| 223 | + name, | |
| 224 | + formData, | |
| 225 | + header, | |
| 226 | + success(res) { | |
| 227 | + resolve(res); | |
| 228 | + }, | |
| 229 | + fail(err) { | |
| 230 | + reject(res); | |
| 231 | + }, | |
| 232 | + }); | |
| 233 | + }); | |
| 234 | +}; | |
| 235 | + | |
| 236 | +//封装uniapp uniapp.chooseImage | |
| 237 | +export const useChooseImage = (data) => { | |
| 238 | + return new Promise((resolve, reject) => { | |
| 239 | + uni.chooseImage({ | |
| 240 | + count: data.count || 1, //默认1 | |
| 241 | + sizeType: data.sizeType || ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有 | |
| 242 | + sourceType: data.sourceType || ["album", "camera"], //从相册选择 | |
| 243 | + success: function(res) { | |
| 244 | + resolve(res.tempFiles); | |
| 245 | + }, | |
| 246 | + fail: (err) => { | |
| 247 | + reject({ | |
| 248 | + errMsg: err.errMsg, | |
| 249 | + errCode: err.errCode, | |
| 250 | + statusCode: 0, | |
| 251 | + }); | |
| 252 | + }, | |
| 157 | 253 | }); |
| 254 | + }); | |
| 255 | +}; | |
| 256 | + | |
| 257 | +//文件上传校验 | |
| 258 | +export const useFileValidate = (file, fileSize) => { | |
| 259 | + if (file.size > fileSize) { | |
| 260 | + useShowToast("上传的图片大小不能超过5M", 2000, true); | |
| 261 | + throw Error("上传的图片大小不能超过5M"); | |
| 158 | 262 | } |
| 159 | -} | |
| \ No newline at end of file | ||
| 263 | + const fileTxt = file.path.split(".").pop(); | |
| 264 | + const fileTypeList = ["jpg", "jpeg", "png"]; | |
| 265 | + if (!fileTypeList.includes(fileTxt)) { | |
| 266 | + useShowToast("请上传指定图片类型(jpg、jpeg、png)", 2000, true); | |
| 267 | + throw Error("请上传指定图片类型(jpg、jpeg、png)"); | |
| 268 | + } | |
| 269 | +}; | |
| 270 | + | |
| 271 | +//封装uniapp uni.pageScrollTo | |
| 272 | +export const usePageScrollTo = (scrollTop, duration) => { | |
| 273 | + uni.pageScrollTo({ | |
| 274 | + scrollTop, // 滚动到页面的目标位置 这个是滚动到顶部, 0 | |
| 275 | + duration, // 滚动动画的时长 | |
| 276 | + }); | |
| 277 | +}; | |
| 278 | + | |
| 279 | +//封装uniapp跳转 navigateBack | |
| 280 | +export const useNavigateBack = (delta) => { | |
| 281 | + uni.navigateBack({ | |
| 282 | + delta | |
| 283 | + }); | |
| 284 | +}; | |
| \ No newline at end of file | ... | ... |
publicLoginSubPage/other/code.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <view class="code-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view class="f__login"> | |
| 6 | - <view class="loginPhone"> | |
| 7 | - <view class="phone-main" style="margin-top: 240rpx;"> | |
| 8 | - <text class="text">手机验证码登录</text> | |
| 9 | - <view class="circleStyle"></view> | |
| 10 | - </view> | |
| 11 | - <view class="form-row"><u-input v-model="phone" type="number" placeholder="请输入手机号码" border="bottom"></u-input></view> | |
| 12 | - <view class="form-row"> | |
| 13 | - <u-input type="number" v-model="vCode" placeholder="请输入验证码" border="bottom"> | |
| 14 | - <template slot="suffix"> | |
| 15 | - <view @click="getVcode" class="getvcode">{{ codeText }}</view> | |
| 16 | - </template> | |
| 17 | - </u-input> | |
| 18 | - </view> | |
| 19 | - <button class="submit" size="default" @click="onSubmit"><text class="text">登录</text></button> | |
| 20 | - <view class="u-flex account-style"><view class="content" @click="openAccountFunc">账号密码登录</view></view> | |
| 21 | - <view class="circleStyleBottom"></view> | |
| 22 | - </view> | |
| 23 | - </view> | |
| 24 | - </view> | |
| 25 | -</template> | |
| 26 | - | |
| 27 | -<script> | |
| 28 | -var clear; | |
| 29 | -import { mapState, mapMutations, mapActions } from 'vuex'; | |
| 30 | -export default { | |
| 31 | - data() { | |
| 32 | - return { | |
| 33 | - readonly: false, | |
| 34 | - codeText: '发送验证码', | |
| 35 | - phone: '', //号码 | |
| 36 | - vCode: '' //验证码 | |
| 37 | - }; | |
| 38 | - }, | |
| 39 | - methods: { | |
| 40 | - ...mapMutations(['setUserInfo']), | |
| 41 | - ...mapActions(['updateBadgeTotal']), | |
| 42 | - //验证码按钮文字状态 | |
| 43 | - getCodeState() { | |
| 44 | - const _this = this; | |
| 45 | - this.readonly = true; | |
| 46 | - this.codeText = '60s后重新获取'; | |
| 47 | - var s = 60; | |
| 48 | - clear = setInterval(() => { | |
| 49 | - s--; | |
| 50 | - _this.codeText = s + 's后重新获取'; | |
| 51 | - if (s <= 0) { | |
| 52 | - clearInterval(clear); | |
| 53 | - _this.codeText = '发送验证码'; | |
| 54 | - _this.readonly = false; | |
| 55 | - } | |
| 56 | - }, 1000); | |
| 57 | - }, | |
| 58 | - //获取验证码 | |
| 59 | - getVcode() { | |
| 60 | - if (this.readonly) { | |
| 61 | - uni.showToast({ | |
| 62 | - title: '验证码已发送~', | |
| 63 | - icon: 'none' | |
| 64 | - }); | |
| 65 | - return; | |
| 66 | - } | |
| 67 | - if (this.phone == '') { | |
| 68 | - uni.showToast({ | |
| 69 | - title: '请输入手机号~', | |
| 70 | - icon: 'none' | |
| 71 | - }); | |
| 72 | - return; | |
| 73 | - } | |
| 74 | - const phoneRegular = /^1\d{10}$/; | |
| 75 | - if (!phoneRegular.test(this.phone)) { | |
| 76 | - uni.showToast({ | |
| 77 | - title: '手机号格式不正确~', | |
| 78 | - icon: 'none' | |
| 79 | - }); | |
| 80 | - return; | |
| 81 | - } | |
| 82 | - // 获取验证码接口 | |
| 83 | - uni.$u.http | |
| 84 | - .post(`/yt/noauth/send_login_code/${this.phone}`) | |
| 85 | - .then(res => { | |
| 86 | - if (res) { | |
| 87 | - this.getCodeState(); //开始倒计时 | |
| 88 | - } | |
| 89 | - }) | |
| 90 | - .catch(err => { | |
| 91 | - uni.showToast({ | |
| 92 | - title: err.data.msg, | |
| 93 | - icon: 'none' | |
| 94 | - }); | |
| 95 | - }); | |
| 96 | - }, | |
| 97 | - onSubmit() { | |
| 98 | - const phoneRegular = /^1\d{10}$/; | |
| 99 | - if (this.phone == '') { | |
| 100 | - uni.showToast({ | |
| 101 | - title: '请输入手机号码~', | |
| 102 | - icon: 'none' | |
| 103 | - }); | |
| 104 | - return; | |
| 105 | - } else if (!phoneRegular.test(this.phone)) { | |
| 106 | - uni.showToast({ | |
| 107 | - title: '手机号格式不正确~', | |
| 108 | - icon: 'none' | |
| 109 | - }); | |
| 110 | - return; | |
| 111 | - } | |
| 112 | - if (this.vCode == '') { | |
| 113 | - uni.showToast({ | |
| 114 | - title: '请输入验证码~', | |
| 115 | - icon: 'none' | |
| 116 | - }); | |
| 117 | - return; | |
| 118 | - } else if (!/^\d{6}$/.test(this.vCode)) { | |
| 119 | - uni.showToast({ | |
| 120 | - title: '验证码格式不正确~', | |
| 121 | - icon: 'none' | |
| 122 | - }); | |
| 123 | - return; | |
| 124 | - } | |
| 125 | - let httpData = { | |
| 126 | - code: this.vCode, | |
| 127 | - phoneNumber: this.phone | |
| 128 | - }; | |
| 129 | - uni.$u.http.post('/yt/auth/code/login', httpData).then(res => { | |
| 130 | - if (res) { | |
| 131 | - // 储存登录信息 | |
| 132 | - let resObj = { | |
| 133 | - refreshToken: res.refreshToken, | |
| 134 | - isToken: res.token | |
| 135 | - }; | |
| 136 | - let userInfo = { | |
| 137 | - ...resObj, | |
| 138 | - token: true, //token用于判断是否登录 | |
| 139 | - isThirdLogin: false | |
| 140 | - }; | |
| 141 | - if (userInfo.token) { | |
| 142 | - this.setUserInfo(userInfo); | |
| 143 | - } | |
| 144 | - uni.showToast({ | |
| 145 | - title: '登录成功~', | |
| 146 | - icon: 'none' | |
| 147 | - }).then(async res => { | |
| 148 | - this.saveUserInfo(); | |
| 149 | - await this.getAlarmTotalData(); | |
| 150 | - uni.reLaunch({ | |
| 151 | - url: '/pages/personal/personal' | |
| 152 | - }); | |
| 153 | - }); | |
| 154 | - } | |
| 155 | - }); | |
| 156 | - }, | |
| 157 | - async getAlarmTotalData() { | |
| 158 | - const res = await uni.$u.http.get('/yt/homepage/app?login=true'); | |
| 159 | - if (res) { | |
| 160 | - //异步实时更新告警徽标数 | |
| 161 | - this.updateBadgeTotal(res.totalAlarm?.activedAlarm); | |
| 162 | - } | |
| 163 | - }, | |
| 164 | - saveUserInfo() { | |
| 165 | - //储存个人信息 | |
| 166 | - uni.$u.http.get('/yt/user/me/info').then(res => { | |
| 167 | - if (res) { | |
| 168 | - this.setUserInfo(res); | |
| 169 | - } | |
| 170 | - }); | |
| 171 | - }, | |
| 172 | - openAccountFunc() { | |
| 173 | - uni.navigateTo({ | |
| 174 | - url: '../public/login' | |
| 175 | - }); | |
| 176 | - } | |
| 177 | - } | |
| 178 | -}; | |
| 179 | -</script> | |
| 180 | - | |
| 181 | -<style lang="scss" scoped> | |
| 182 | -@import './static/code.scss'; | |
| 183 | -</style> |
publicLoginSubPage/other/findPassword.vue
deleted
100644 → 0
| 1 | -<template> | |
| 2 | - <view class="find-password-page"> | |
| 3 | - <public-module></public-module> | |
| 4 | - <view class="top u-flex"> | |
| 5 | - <view @click="showPhone" :style="{ color: !nextStatus ? '#0079fe' : '' }" class="item">1.验证手机号码</view> | |
| 6 | - <view :style="{ color: !nextStatus ? '' : '#0079fe' }" class="item">2.设置新密码</view> | |
| 7 | - </view> | |
| 8 | - <view v-if="!nextStatus" style="margin-top: 40rpx;" class="f__login"> | |
| 9 | - <view class="loginPhone"> | |
| 10 | - <view class="form-row"> | |
| 11 | - <u-input v-model="phone" type="number" placeholder="请输入手机号码" border="bottom" /> | |
| 12 | - </view> | |
| 13 | - <view class="form-row"> | |
| 14 | - <u-input type="number" v-model="vCode" placeholder="请输入验证码" border="bottom"> | |
| 15 | - <template slot="suffix"> | |
| 16 | - <view @click="getVcode" class="getvcode">{{ codeText }}</view> | |
| 17 | - </template> | |
| 18 | - </u-input> | |
| 19 | - </view> | |
| 20 | - <button class="submit" size="default" @click="onNextSubmit"><text style="color:#fff">下一步</text></button> | |
| 21 | - </view> | |
| 22 | - </view> | |
| 23 | - <view v-else style="margin-top: 40rpx;" class="f__login"> | |
| 24 | - <view class="loginPhone"> | |
| 25 | - <view class="form-row u-flex"> | |
| 26 | - <u-input v-model="password" :password="showPasswordF" placeholder="请设置6-20位新的登录密码" border="bottom"> | |
| 27 | - <template slot="suffix"> | |
| 28 | - <view @click="showPasswordMode" style="padding: 10rpx"> | |
| 29 | - <u-icon width="18" height="14" :name=" | |
| 30 | - showPasswordF ? '/static/eye-hide.png' : '/static/eye.png' | |
| 31 | - "></u-icon> | |
| 32 | - </view> | |
| 33 | - </template> | |
| 34 | - </u-input> | |
| 35 | - </view> | |
| 36 | - <view class="form-row u-flex"> | |
| 37 | - <u-input v-model="rePassword" :password="showPasswordS" placeholder="请再次输入新的登录密码" border="bottom"> | |
| 38 | - <template slot="suffix"> | |
| 39 | - <view @click="showPasswordModeS" style="padding: 10rpx"> | |
| 40 | - <u-icon width="18" height="14" :name=" | |
| 41 | - showPasswordS ? '/static/eye-hide.png' : '/static/eye.png' | |
| 42 | - "></u-icon> | |
| 43 | - </view> | |
| 44 | - </template> | |
| 45 | - </u-input> | |
| 46 | - </view> | |
| 47 | - <button class="submit" size="default" @click="onSubmit"><text style="color:#fff">确定</text></button> | |
| 48 | - </view> | |
| 49 | - </view> | |
| 50 | - </view> | |
| 51 | -</template> | |
| 52 | - | |
| 53 | -<script> | |
| 54 | - import api from '@/api/index.js' | |
| 55 | - import { loginPasswordReg } from '@/plugins/utils.js' | |
| 56 | - | |
| 57 | - var clear; | |
| 58 | - export default { | |
| 59 | - data() { | |
| 60 | - return { | |
| 61 | - readonly: false, | |
| 62 | - codeText: '发送验证码', | |
| 63 | - phone: '', //号码 | |
| 64 | - vCode: '', //验证码 | |
| 65 | - nextStatus: false, | |
| 66 | - password: '', | |
| 67 | - rePassword: '', | |
| 68 | - showPasswordF: true, | |
| 69 | - showPasswordS: true | |
| 70 | - }; | |
| 71 | - }, | |
| 72 | - methods: { | |
| 73 | - //验证码按钮文字状态 | |
| 74 | - getCodeState() { | |
| 75 | - const _this = this; | |
| 76 | - this.readonly = true; | |
| 77 | - this.codeText = '60s后重新获取'; | |
| 78 | - var s = 60; | |
| 79 | - clear = setInterval(() => { | |
| 80 | - s--; | |
| 81 | - _this.codeText = s + 's后重新获取'; | |
| 82 | - if (s <= 0) { | |
| 83 | - clearInterval(clear); | |
| 84 | - _this.codeText = '发送验证码'; | |
| 85 | - _this.readonly = false; | |
| 86 | - } | |
| 87 | - }, 1000); | |
| 88 | - }, | |
| 89 | - //获取验证码 | |
| 90 | - getVcode() { | |
| 91 | - if (this.readonly) { | |
| 92 | - uni.showToast({ | |
| 93 | - title: '验证码已发送~', | |
| 94 | - icon: 'none' | |
| 95 | - }); | |
| 96 | - return; | |
| 97 | - } | |
| 98 | - if (this.phone == '') { | |
| 99 | - uni.showToast({ | |
| 100 | - title: '请输入手机号~', | |
| 101 | - icon: 'none' | |
| 102 | - }); | |
| 103 | - return; | |
| 104 | - } | |
| 105 | - const phoneRegular = /^1\d{10}$/; | |
| 106 | - if (!phoneRegular.test(this.phone)) { | |
| 107 | - uni.showToast({ | |
| 108 | - title: '手机号格式不正确~', | |
| 109 | - icon: 'none' | |
| 110 | - }); | |
| 111 | - return; | |
| 112 | - } | |
| 113 | - let httpData = {}; | |
| 114 | - // 获取验证码接口 | |
| 115 | - api.loginApi.postCodeApi(this.phone) | |
| 116 | - .then(res => { | |
| 117 | - this.getCodeState(); //开始倒计时 | |
| 118 | - }) | |
| 119 | - .catch(err => { | |
| 120 | - uni.showToast({ | |
| 121 | - title: err.data.msg, | |
| 122 | - icon: 'none' | |
| 123 | - }); | |
| 124 | - }); | |
| 125 | - }, | |
| 126 | - onNextSubmit() { | |
| 127 | - const phoneRegular = /^1\d{10}$/; | |
| 128 | - if (this.phone == '') { | |
| 129 | - uni.showToast({ | |
| 130 | - title: '请输入手机号码~', | |
| 131 | - icon: 'none' | |
| 132 | - }); | |
| 133 | - return; | |
| 134 | - } else if (!phoneRegular.test(this.phone)) { | |
| 135 | - uni.showToast({ | |
| 136 | - title: '手机号格式不正确~', | |
| 137 | - icon: 'none' | |
| 138 | - }); | |
| 139 | - return; | |
| 140 | - } | |
| 141 | - if (this.vCode == '') { | |
| 142 | - uni.showToast({ | |
| 143 | - title: '请输入验证码~', | |
| 144 | - icon: 'none' | |
| 145 | - }); | |
| 146 | - return; | |
| 147 | - } else if (!/^\d{6}$/.test(this.vCode)) { | |
| 148 | - uni.showToast({ | |
| 149 | - title: '验证码格式不正确~', | |
| 150 | - icon: 'none' | |
| 151 | - }); | |
| 152 | - return; | |
| 153 | - } | |
| 154 | - this.nextStatus = true; | |
| 155 | - }, | |
| 156 | - showPhone() { | |
| 157 | - this.nextStatus = false; | |
| 158 | - }, | |
| 159 | - onSubmit() { | |
| 160 | - if (this.password == '' && this.rePassword == '') { | |
| 161 | - uni.showToast({ | |
| 162 | - title: '请输入密码~', | |
| 163 | - icon: 'none' | |
| 164 | - }); | |
| 165 | - return; | |
| 166 | - } else if (!loginPasswordReg.test(this.password) && !loginPasswordReg.test(this.rePassword)) { | |
| 167 | - //uni.showToast,字数过长,会造成手机上显示不完全,官方bug,采用uni.showModal | |
| 168 | - uni.showModal({ | |
| 169 | - title: '提示', | |
| 170 | - content: '密码格式不正确(至少一个大写英文字母、至少一个小写英文字母、至少一位数字、至少一个特殊字符、最少八个字符)~', | |
| 171 | - showCancel: false | |
| 172 | - }); | |
| 173 | - return; | |
| 174 | - } | |
| 175 | - if (this.password !== this.rePassword) return uni.$u.toast('两次输入密码不一致'); | |
| 176 | - let httpData = { | |
| 177 | - password: this.password, | |
| 178 | - phoneNumber: this.phone, | |
| 179 | - userId: this.vCode | |
| 180 | - }; | |
| 181 | - const res = api.loginApi.postResetCodeApi(this.phone, httpData) | |
| 182 | - if (res) { | |
| 183 | - uni.showToast({ | |
| 184 | - title: '重置密码成功~', | |
| 185 | - icon: 'none' | |
| 186 | - }).then(res => { | |
| 187 | - uni.reLaunch({ | |
| 188 | - url: '/publicLoginSubPage/public/login' | |
| 189 | - }); | |
| 190 | - }); | |
| 191 | - } | |
| 192 | - }, | |
| 193 | - showPasswordMode() { | |
| 194 | - this.showPasswordF = !this.showPasswordF; | |
| 195 | - }, | |
| 196 | - showPasswordModeS() { | |
| 197 | - this.showPasswordS = !this.showPasswordS; | |
| 198 | - } | |
| 199 | - } | |
| 200 | - }; | |
| 201 | -</script> | |
| 202 | - | |
| 203 | -<style lang="scss" scoped> | |
| 204 | - @import './static/findPassword.scss'; | |
| 205 | -</style> |
| ... | ... | @@ -47,6 +47,63 @@ button { |
| 47 | 47 | white-space: nowrap; |
| 48 | 48 | } |
| 49 | 49 | ///////////////////////////////////////////////////////////////小程序、app抽取公共样式///////////////////////////////////////////////////////////////////// |
| 50 | +.flex-column{ | |
| 51 | + display: flex; | |
| 52 | + flex-direction: column; | |
| 53 | +} | |
| 54 | +.flex{ | |
| 55 | + display: flex; | |
| 56 | +} | |
| 57 | +.justify-center{ | |
| 58 | + display: flex; | |
| 59 | + justify-content: center; | |
| 60 | + align-items: center; | |
| 61 | +} | |
| 62 | +.mt-3{ | |
| 63 | + margin-top: 30rpx; | |
| 64 | +} | |
| 65 | +.ml-16{ | |
| 66 | + margin-left: 16rpx; | |
| 67 | +} | |
| 68 | +.mt-15{ | |
| 69 | + margin-top: 15rpx; | |
| 70 | +} | |
| 71 | +.mt-20{ | |
| 72 | + margin-top: 20rpx; | |
| 73 | +} | |
| 74 | +.mr-1{ | |
| 75 | + margin-right: 10rpx; | |
| 76 | +} | |
| 77 | +.mr-2{ | |
| 78 | + margin-right: 20rpx; | |
| 79 | +} | |
| 80 | +.ml-3{ | |
| 81 | + margin-top: 20rpx; | |
| 82 | +} | |
| 83 | +.ml-1{ | |
| 84 | + margin-left: 10rpx; | |
| 85 | +} | |
| 86 | +.pl-3{ | |
| 87 | + padding-left: 30rpx; | |
| 88 | +} | |
| 89 | +.w-100{ | |
| 90 | + width: 100%; | |
| 91 | +} | |
| 92 | +.w-300{ | |
| 93 | + width:300rpx; | |
| 94 | +} | |
| 95 | +.w-500{ | |
| 96 | + width:500rpx; | |
| 97 | +} | |
| 98 | +.h-25{ | |
| 99 | + height:25rpx; | |
| 100 | +} | |
| 101 | +.h-30{ | |
| 102 | + height:30rpx; | |
| 103 | +} | |
| 104 | +.h-140{ | |
| 105 | + height:140rpx; | |
| 106 | +} | |
| 50 | 107 | //通用(设备、告警、摄像头分页头部组织和设备数和设备、告警里面的详情(左边的文本) |
| 51 | 108 | .ml-10{ |
| 52 | 109 | margin-left: 10rpx; | ... | ... |
sysnotify-subpackage/sys-notify/notify-detail.vue
renamed from
sysNotifySubPage/sysNotifyPage/notifyDetail.vue
| 1 | -<template> | |
| 2 | - <view class="notify-detail-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view class="notify-column"> | |
| 6 | - <view class="column-list"> | |
| 7 | - <view class="column-title"> | |
| 8 | - <view class="text-clip" style="width:500rpx"> | |
| 9 | - <text class="notify-detail-text ">{{ notifyList.title }}</text> | |
| 10 | - </view> | |
| 11 | - </view> | |
| 12 | - <view style="height: 25rpx;"></view> | |
| 13 | - <u-list height="140rpx"> | |
| 14 | - <u-list-item> | |
| 15 | - <u-cell :value="`${notifyList.senderDate}`" :title="`${notifyList.senderName}`"> | |
| 16 | - <u-avatar slot="icon" shape="circle" size="35" :src="notifyList.avatar"></u-avatar> | |
| 17 | - </u-cell> | |
| 18 | - </u-list-item> | |
| 19 | - </u-list> | |
| 20 | - <view class="bottom-text"> | |
| 21 | - <view class="u-flex column"></view> | |
| 22 | - <view style="margin-top: 21rpx;"> | |
| 23 | - <!-- 富文本解析 --> | |
| 24 | - <u-parse :content="notifyList.content"></u-parse> | |
| 25 | - <!-- 富文本解析 --> | |
| 26 | - </view> | |
| 27 | - </view> | |
| 28 | - </view> | |
| 29 | - </view> | |
| 30 | - </view> | |
| 31 | -</template> | |
| 32 | - | |
| 33 | -<script> | |
| 34 | -export default { | |
| 35 | - data() { | |
| 36 | - return { | |
| 37 | - notifyList: {} | |
| 38 | - }; | |
| 39 | - }, | |
| 40 | - onLoad(e) { | |
| 41 | - // 隐藏原生的tabbar | |
| 42 | - uni.hideTabBar(); | |
| 43 | - if (e.data !== null) { | |
| 44 | - let params = JSON.parse(decodeURIComponent(e.data)); | |
| 45 | - if (params) this.notifyList = params; | |
| 46 | - } | |
| 47 | - } | |
| 48 | -}; | |
| 49 | -</script> | |
| 50 | - | |
| 51 | -<style lang="scss" scoped> | |
| 52 | -@import './static/notifyDetail.scss'; | |
| 53 | -/deep/ .u-line { | |
| 54 | - position: relative !important; | |
| 55 | - width: 640rpx !important; | |
| 56 | - left: 31rpx !important; | |
| 57 | -} | |
| 58 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="notify-detail-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view class="notify-column"> | |
| 6 | + <view class="column-list"> | |
| 7 | + <view class="column-title"> | |
| 8 | + <view class="text-clip w-500"> | |
| 9 | + <text class="notify-detail-text ">{{ notifyList.title }}</text> | |
| 10 | + </view> | |
| 11 | + </view> | |
| 12 | + <view class="h-25"></view> | |
| 13 | + <u-list height="140rpx"> | |
| 14 | + <u-list-item> | |
| 15 | + <u-cell :value="`${notifyList.senderDate}`" :title="`${notifyList.senderName}`"> | |
| 16 | + <u-avatar slot="icon" shape="circle" size="35" :src="notifyList.avatar"></u-avatar> | |
| 17 | + </u-cell> | |
| 18 | + </u-list-item> | |
| 19 | + </u-list> | |
| 20 | + <view class="bottom-text"> | |
| 21 | + <view class="u-flex column"></view> | |
| 22 | + <view class="mt-20"> | |
| 23 | + <!-- 富文本解析 --> | |
| 24 | + <u-parse :content="notifyList.content"></u-parse> | |
| 25 | + </view> | |
| 26 | + </view> | |
| 27 | + </view> | |
| 28 | + </view> | |
| 29 | + </view> | |
| 30 | +</template> | |
| 31 | + | |
| 32 | +<script> | |
| 33 | +export default { | |
| 34 | + data() { | |
| 35 | + return { | |
| 36 | + notifyList: {} | |
| 37 | + }; | |
| 38 | + }, | |
| 39 | + onLoad(e) { | |
| 40 | + // 隐藏原生的tabbar | |
| 41 | + uni.hideTabBar(); | |
| 42 | + if (e.data !== null) { | |
| 43 | + let params = JSON.parse(decodeURIComponent(e.data)); | |
| 44 | + if (params) this.notifyList = params; | |
| 45 | + } | |
| 46 | + } | |
| 47 | +}; | |
| 48 | +</script> | |
| 49 | + | |
| 50 | +<style lang="scss" scoped> | |
| 51 | +@import './static/notifyDetail.scss'; | |
| 52 | +/deep/ .u-line { | |
| 53 | + position: relative !important; | |
| 54 | + width: 640rpx !important; | |
| 55 | + left: 31rpx !important; | |
| 56 | +} | |
| 57 | +</style> | ... | ... |
sysnotify-subpackage/sys-notify/static/notifyDetail.scss
renamed from
sysNotifySubPage/sysNotifyPage/static/notifyDetail.scss
| 1 | -.notify-detail-page { | |
| 2 | - min-height: 100vh; | |
| 3 | - background-color: #f8f9fa; | |
| 4 | - padding-top: 10rpx; | |
| 5 | - padding-left: 27rpx; | |
| 6 | -} | |
| 7 | -.notify-column { | |
| 8 | - .column-list { | |
| 9 | - border-radius: 10px; | |
| 10 | - margin-top: 20rpx; | |
| 11 | - width: 696rpx; | |
| 12 | - height: 1000rpx; | |
| 13 | - background-color: #ffffff; | |
| 14 | - .column-title{ | |
| 15 | - margin-left: 36rpx; | |
| 16 | - position: relative; | |
| 17 | - top: 21rpx; | |
| 18 | - } | |
| 19 | - .bottom-text { | |
| 20 | - margin-left: 33rpx; | |
| 21 | - .text { | |
| 22 | - color: #2e384d; | |
| 23 | - font-size: 15px; | |
| 24 | - } | |
| 25 | - .column { | |
| 26 | - margin-top: 20rpx; | |
| 27 | - .text { | |
| 28 | - font-size: 16px; | |
| 29 | - font-family: PingFangSC-Medium, PingFang SC; | |
| 30 | - font-weight: 500; | |
| 31 | - color: #2e384d; | |
| 32 | - } | |
| 33 | - } | |
| 34 | - } | |
| 35 | - } | |
| 36 | -} | |
| 1 | +.notify-detail-page { | |
| 2 | + min-height: 100vh; | |
| 3 | + background-color: #f8f9fa; | |
| 4 | + padding-top: 10rpx; | |
| 5 | + padding-left: 27rpx; | |
| 6 | +} | |
| 7 | +.notify-column { | |
| 8 | + .column-list { | |
| 9 | + border-radius: 10px; | |
| 10 | + margin-top: 20rpx; | |
| 11 | + width: 696rpx; | |
| 12 | + height: 1000rpx; | |
| 13 | + background-color: #ffffff; | |
| 14 | + .column-title{ | |
| 15 | + margin-left: 36rpx; | |
| 16 | + position: relative; | |
| 17 | + top: 21rpx; | |
| 18 | + } | |
| 19 | + .bottom-text { | |
| 20 | + margin-left: 33rpx; | |
| 21 | + .text { | |
| 22 | + color: #2e384d; | |
| 23 | + font-size: 15px; | |
| 24 | + } | |
| 25 | + .column { | |
| 26 | + margin-top: 20rpx; | |
| 27 | + .text { | |
| 28 | + font-size: 16px; | |
| 29 | + font-family: PingFangSC-Medium, PingFang SC; | |
| 30 | + font-weight: 500; | |
| 31 | + color: #2e384d; | |
| 32 | + } | |
| 33 | + } | |
| 34 | + } | |
| 35 | + } | |
| 36 | +} | ... | ... |
sysnotify-subpackage/sys-notify/static/systemNotify.scss
renamed from
sysNotifySubPage/sysNotifyPage/static/systemNotify.scss
| 1 | -.notify-page { | |
| 2 | - min-height: 100vh; | |
| 3 | - background-color: #f8f9fa; | |
| 4 | - padding-top: 10rpx; | |
| 5 | - padding-left: 27rpx; | |
| 6 | - .notify-page-top-select{ | |
| 7 | - width: 750rpx; | |
| 8 | - height:53rpx; | |
| 9 | - background-color: #f8f9fa; | |
| 10 | - position:fixed; | |
| 11 | - top:0; | |
| 12 | - z-index: 99999; | |
| 13 | - } | |
| 14 | - .top-select{ | |
| 15 | - background-color: #f8f9fa; | |
| 16 | - width: 700rpx; | |
| 17 | - position: relative; | |
| 18 | - top: 35rpx; | |
| 19 | - } | |
| 20 | -} | |
| 21 | -/deep/.u-list-item { | |
| 22 | - background: #ffffff; | |
| 23 | - width: 695rpx; | |
| 24 | - border-radius: 10px; | |
| 25 | - margin-top: 20rpx; | |
| 26 | -} | |
| 27 | -.notify-main { | |
| 28 | - .main { | |
| 29 | - flex-direction: column; | |
| 30 | - margin-left: -22rpx; | |
| 31 | - .main-item { | |
| 32 | - justify-content: space-between; | |
| 33 | - flex-direction: row; | |
| 34 | - margin: 15rpx; | |
| 35 | - width: 700rpx; | |
| 36 | - height: 136rpx; | |
| 37 | - background: #ffffff; | |
| 38 | - border-radius: 10px; | |
| 39 | - .item { | |
| 40 | - justify-content: space-between; | |
| 41 | - flex-direction: row; | |
| 42 | - .item-avatar { | |
| 43 | - margin-left: 30rpx; | |
| 44 | - .avatar { | |
| 45 | - margin-left: 30rpx; | |
| 46 | - } | |
| 47 | - } | |
| 48 | - .item-content { | |
| 49 | - margin-left: 30rpx; | |
| 50 | - text-align: left; | |
| 51 | - justify-content: space-between; | |
| 52 | - flex-direction: column; | |
| 53 | - .text-top { | |
| 54 | - width: 400rpx; | |
| 55 | - color: #2e384d; | |
| 56 | - font-size: 15px; | |
| 57 | - } | |
| 58 | - .text-bottom { | |
| 59 | - width: 400rpx; | |
| 60 | - color: #999999; | |
| 61 | - font-size: 13px; | |
| 62 | - } | |
| 63 | - } | |
| 64 | - } | |
| 65 | - .item-right { | |
| 66 | - .text { | |
| 67 | - margin-right: 30rpx; | |
| 68 | - color: #999999; | |
| 69 | - font-size: 13px; | |
| 70 | - } | |
| 71 | - } | |
| 72 | - } | |
| 73 | - } | |
| 74 | -} | |
| 1 | +.notify-page { | |
| 2 | + min-height: 100vh; | |
| 3 | + background-color: #f8f9fa; | |
| 4 | + padding-top: 10rpx; | |
| 5 | + padding-left: 27rpx; | |
| 6 | + .notify-page-top-select{ | |
| 7 | + width: 750rpx; | |
| 8 | + height:53rpx; | |
| 9 | + background-color: #f8f9fa; | |
| 10 | + position:fixed; | |
| 11 | + top:0; | |
| 12 | + z-index: 99999; | |
| 13 | + } | |
| 14 | + .top-select{ | |
| 15 | + background-color: #f8f9fa; | |
| 16 | + width: 700rpx; | |
| 17 | + position: relative; | |
| 18 | + top: 35rpx; | |
| 19 | + } | |
| 20 | +} | |
| 21 | +/deep/.u-list-item { | |
| 22 | + background: #ffffff; | |
| 23 | + width: 695rpx; | |
| 24 | + border-radius: 10px; | |
| 25 | + margin-top: 20rpx; | |
| 26 | +} | |
| 27 | +.notify-main { | |
| 28 | + .main { | |
| 29 | + flex-direction: column; | |
| 30 | + margin-left: -22rpx; | |
| 31 | + .main-item { | |
| 32 | + justify-content: space-between; | |
| 33 | + flex-direction: row; | |
| 34 | + margin: 15rpx; | |
| 35 | + width: 700rpx; | |
| 36 | + height: 136rpx; | |
| 37 | + background: #ffffff; | |
| 38 | + border-radius: 10px; | |
| 39 | + .item { | |
| 40 | + justify-content: space-between; | |
| 41 | + flex-direction: row; | |
| 42 | + .item-avatar { | |
| 43 | + margin-left: 30rpx; | |
| 44 | + .avatar { | |
| 45 | + margin-left: 30rpx; | |
| 46 | + } | |
| 47 | + } | |
| 48 | + .item-content { | |
| 49 | + margin-left: 30rpx; | |
| 50 | + text-align: left; | |
| 51 | + justify-content: space-between; | |
| 52 | + flex-direction: column; | |
| 53 | + .text-top { | |
| 54 | + width: 400rpx; | |
| 55 | + color: #2e384d; | |
| 56 | + font-size: 15px; | |
| 57 | + } | |
| 58 | + .text-bottom { | |
| 59 | + width: 400rpx; | |
| 60 | + color: #999999; | |
| 61 | + font-size: 13px; | |
| 62 | + } | |
| 63 | + } | |
| 64 | + } | |
| 65 | + .item-right { | |
| 66 | + .text { | |
| 67 | + margin-right: 30rpx; | |
| 68 | + color: #999999; | |
| 69 | + font-size: 13px; | |
| 70 | + } | |
| 71 | + } | |
| 72 | + } | |
| 73 | + } | |
| 74 | +} | ... | ... |
sysnotify-subpackage/sys-notify/system-notify.vue
renamed from
sysNotifySubPage/sysNotifyPage/systemNotify.vue
| 1 | -<template> | |
| 2 | - <view class="notify-page"> | |
| 3 | - <!-- 公共组件-每个页面必须引入 --> | |
| 4 | - <public-module></public-module> | |
| 5 | - <view class="notify-page-top-select"> | |
| 6 | - <view @click="handleTypeClick" class="top-select"> | |
| 7 | - <u--input suffixIcon="arrow-down" shape="circle" disabled v-model="notifyType" | |
| 8 | - placeholder="请选择类型" border="surround"></u--input> | |
| 9 | - <u-action-sheet safe-area-inset-bottom :show="showType" :actions="actions" title="请选择类型" @close="showType = false" | |
| 10 | - @select="handleTypeSelect"></u-action-sheet> | |
| 11 | - </view> | |
| 12 | - </view> | |
| 13 | - <view style="height: 110rpx;"></view> | |
| 14 | - <view class="notify-main"> | |
| 15 | - <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 16 | - @up="upCallback"> | |
| 17 | - <view class="u-flex main"> | |
| 18 | - <view @click="handleNotifyDetail(item, index)" class="u-flex main-item" v-for="(item, index) in list" | |
| 19 | - :key="index"> | |
| 20 | - <view class="u-flex item"> | |
| 21 | - <view class="item-avatar"> | |
| 22 | - <u-avatar class="avatar" shape="circle" size="40" :src="item.sysNotice.avatar"> | |
| 23 | - </u-avatar> | |
| 24 | - </view> | |
| 25 | - <view class="u-flex item-content"> | |
| 26 | - <text class="text-top text-clip">{{ item.sysNotice.title }}</text> | |
| 27 | - <text class="text-bottom text-clip">{{ item.sysNotice.senderDate }}</text> | |
| 28 | - </view> | |
| 29 | - </view> | |
| 30 | - <view class="item-right u-flex" style="justify-content: space-between;"> | |
| 31 | - <text class="text">{{ formatType(item.sysNotice.type) }}</text> | |
| 32 | - <!-- readStatus===0则阅读状态表示未阅读 --> | |
| 33 | - <u-badge style="margin-right: 10rpx;" v-if="item.readStatus == '0'" numberType="overflow" | |
| 34 | - isDot /> | |
| 35 | - </view> | |
| 36 | - </view> | |
| 37 | - </view> | |
| 38 | - </mescroll-body> | |
| 39 | - </view> | |
| 40 | - </view> | |
| 41 | -</template> | |
| 42 | - | |
| 43 | -<script> | |
| 44 | - import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 45 | - import api from '@/api/index.js' | |
| 46 | - import { useNavigateTo } from '@/plugins/utils.js' | |
| 47 | - | |
| 48 | - export default { | |
| 49 | - mixins: [MescrollMixin], | |
| 50 | - data() { | |
| 51 | - return { | |
| 52 | - notifyType:'', | |
| 53 | - showType: false, | |
| 54 | - actions: [{ | |
| 55 | - name: '全部', | |
| 56 | - value: '' | |
| 57 | - }, | |
| 58 | - { | |
| 59 | - name: '会议', | |
| 60 | - value: 'MEETING' | |
| 61 | - }, | |
| 62 | - { | |
| 63 | - name: '公告', | |
| 64 | - value: 'NOTICE' | |
| 65 | - }, | |
| 66 | - { | |
| 67 | - name: '其他', | |
| 68 | - value: 'OTHER' | |
| 69 | - } | |
| 70 | - ], | |
| 71 | - page: { | |
| 72 | - page: 0, | |
| 73 | - pageSize: 10 | |
| 74 | - }, | |
| 75 | - downOption: { | |
| 76 | - auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 77 | - }, | |
| 78 | - list: [], | |
| 79 | - selectType: '', | |
| 80 | - distance: 0, | |
| 81 | - }; | |
| 82 | - }, | |
| 83 | - onLoad(e) { | |
| 84 | - // 隐藏原生的tabbar | |
| 85 | - uni.hideTabBar(); | |
| 86 | - }, | |
| 87 | - methods: { | |
| 88 | - formatType(e) { | |
| 89 | - return this.actions.find((item)=>item.value===e && item.value!=='').name | |
| 90 | - }, | |
| 91 | - handleTypeClick() { | |
| 92 | - this.showType = true; | |
| 93 | - uni.hideKeyboard(); | |
| 94 | - }, | |
| 95 | - handleTypeSelect(e) { | |
| 96 | - this.selectType = e.value; | |
| 97 | - this.page.page = 1; | |
| 98 | - this.notifyType = e.name; | |
| 99 | - this.loadData(1, !this.selectType ? null : this.selectType); | |
| 100 | - }, | |
| 101 | - downCallback() { | |
| 102 | - this.list.length = 0; | |
| 103 | - this.page.page = 1; | |
| 104 | - this.loadData(1); | |
| 105 | - this.selectType = ''; | |
| 106 | - this.notifyType = ''; | |
| 107 | - }, | |
| 108 | - upCallback() { | |
| 109 | - if (this.selectType) { | |
| 110 | - this.page.page += 1; | |
| 111 | - this.loadData(this.page.page, this.selectType); | |
| 112 | - } else { | |
| 113 | - this.page.page += 1; | |
| 114 | - this.loadData(this.page.page); | |
| 115 | - } | |
| 116 | - }, | |
| 117 | - async loadData(page, type) { | |
| 118 | - let params = { | |
| 119 | - page, | |
| 120 | - pageSize: 10, | |
| 121 | - type | |
| 122 | - }; | |
| 123 | - const res = await api.notifyApi.getNotifyApi({ | |
| 124 | - params, | |
| 125 | - custom: { | |
| 126 | - load: false | |
| 127 | - } | |
| 128 | - }) | |
| 129 | - uni.stopPullDownRefresh(); | |
| 130 | - this.mescroll.endByPage(res.items.length, res.total); | |
| 131 | - if (page == 1) { | |
| 132 | - this.list = res.items; | |
| 133 | - } else { | |
| 134 | - this.list = this.list.concat(res.items); | |
| 135 | - } | |
| 136 | - }, | |
| 137 | - async handleNotifyDetail(item, index) { | |
| 138 | - this.list[index].readStatus = 1;//点击了则说明阅读了 | |
| 139 | - await api.notifyApi.byNotifyIdGetDetailApi(item.sysNotice.id) | |
| 140 | - useNavigateTo('./notifyDetail?data=', item.sysNotice) | |
| 141 | - } | |
| 142 | - } | |
| 143 | - }; | |
| 144 | -</script> | |
| 145 | - | |
| 146 | -<style lang="scss" scoped> | |
| 147 | - @import './static/systemNotify.scss'; | |
| 148 | - | |
| 149 | - /deep/ .u-badge--error { | |
| 150 | - position: relative; | |
| 151 | - right: 11rpx; | |
| 152 | - } | |
| 153 | -</style> | |
| 1 | +<template> | |
| 2 | + <view class="notify-page"> | |
| 3 | + <!-- 公共组件-每个页面必须引入 --> | |
| 4 | + <public-module></public-module> | |
| 5 | + <view class="notify-page-top-select"> | |
| 6 | + <view @click="handleTypeClick" class="top-select"> | |
| 7 | + <u--input suffixIcon="arrow-down" shape="circle" disabled v-model="notifyType" | |
| 8 | + placeholder="请选择类型" border="surround"></u--input> | |
| 9 | + <u-action-sheet safe-area-inset-bottom :show="showType" :actions="actions" title="请选择类型" @close="showType = false" | |
| 10 | + @select="handleTypeSelect"></u-action-sheet> | |
| 11 | + </view> | |
| 12 | + </view> | |
| 13 | + <view style="height: 110rpx;"></view> | |
| 14 | + <view class="notify-main"> | |
| 15 | + <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" | |
| 16 | + @up="upCallback"> | |
| 17 | + <view class="u-flex main"> | |
| 18 | + <view @click="handleNotifyDetail(item, index)" class="u-flex main-item" v-for="(item, index) in list" | |
| 19 | + :key="index"> | |
| 20 | + <view class="u-flex item"> | |
| 21 | + <view class="item-avatar"> | |
| 22 | + <u-avatar class="avatar" shape="circle" size="40" :src="item.sysNotice.avatar"> | |
| 23 | + </u-avatar> | |
| 24 | + </view> | |
| 25 | + <view class="u-flex item-content"> | |
| 26 | + <text class="text-top text-clip">{{ item.sysNotice.title }}</text> | |
| 27 | + <text class="text-bottom text-clip">{{ item.sysNotice.senderDate }}</text> | |
| 28 | + </view> | |
| 29 | + </view> | |
| 30 | + <view class="item-right u-flex" style="justify-content: space-between;"> | |
| 31 | + <text class="text">{{ formatType(item.sysNotice.type) }}</text> | |
| 32 | + <!-- readStatus===0则阅读状态表示未阅读 --> | |
| 33 | + <u-badge style="margin-right: 10rpx;" v-if="item.readStatus == '0'" numberType="overflow" | |
| 34 | + isDot /> | |
| 35 | + </view> | |
| 36 | + </view> | |
| 37 | + </view> | |
| 38 | + </mescroll-body> | |
| 39 | + </view> | |
| 40 | + </view> | |
| 41 | +</template> | |
| 42 | + | |
| 43 | +<script> | |
| 44 | + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; | |
| 45 | + import api from '@/api/index.js' | |
| 46 | + import { useNavigateTo } from '@/plugins/utils.js' | |
| 47 | + import { actions } from './config/data.js' | |
| 48 | + | |
| 49 | + export default { | |
| 50 | + mixins: [MescrollMixin], | |
| 51 | + data() { | |
| 52 | + return { | |
| 53 | + notifyType:'', | |
| 54 | + showType: false, | |
| 55 | + actions, | |
| 56 | + page: { | |
| 57 | + page: 0, | |
| 58 | + pageSize: 10 | |
| 59 | + }, | |
| 60 | + downOption: { | |
| 61 | + auto: false //是否在初始化后,自动执行downCallback; 默认true | |
| 62 | + }, | |
| 63 | + list: [], | |
| 64 | + selectType: '', | |
| 65 | + distance: 0, | |
| 66 | + }; | |
| 67 | + }, | |
| 68 | + onLoad(e) { | |
| 69 | + // 隐藏原生的tabbar | |
| 70 | + uni.hideTabBar(); | |
| 71 | + }, | |
| 72 | + methods: { | |
| 73 | + formatType(e) { | |
| 74 | + const findName = this.actions.find((item)=>item.value===e && item.value!=='') | |
| 75 | + if(!findName) return | |
| 76 | + return findName.name | |
| 77 | + }, | |
| 78 | + handleTypeClick() { | |
| 79 | + this.showType = true; | |
| 80 | + uni.hideKeyboard(); | |
| 81 | + }, | |
| 82 | + handleTypeSelect(e) { | |
| 83 | + this.selectType = e.value; | |
| 84 | + this.page.page = 1; | |
| 85 | + this.notifyType = e.name; | |
| 86 | + this.loadData(1, !this.selectType ? null : this.selectType); | |
| 87 | + }, | |
| 88 | + downCallback() { | |
| 89 | + this.list.length = 0; | |
| 90 | + this.page.page = 1; | |
| 91 | + this.loadData(1); | |
| 92 | + this.selectType = ''; | |
| 93 | + this.notifyType = ''; | |
| 94 | + }, | |
| 95 | + upCallback() { | |
| 96 | + if (this.selectType) { | |
| 97 | + this.page.page += 1; | |
| 98 | + this.loadData(this.page.page, this.selectType); | |
| 99 | + } else { | |
| 100 | + this.page.page += 1; | |
| 101 | + this.loadData(this.page.page); | |
| 102 | + } | |
| 103 | + }, | |
| 104 | + async loadData(page, type) { | |
| 105 | + let params = { | |
| 106 | + page, | |
| 107 | + pageSize: 10, | |
| 108 | + type | |
| 109 | + }; | |
| 110 | + const res = await api.notifyApi.getNotifyApi({ | |
| 111 | + params, | |
| 112 | + custom: { | |
| 113 | + load: false | |
| 114 | + } | |
| 115 | + }) | |
| 116 | + uni.stopPullDownRefresh(); | |
| 117 | + this.mescroll.endByPage(res.items.length, res.total); | |
| 118 | + if (page == 1) { | |
| 119 | + this.list = res.items; | |
| 120 | + } else { | |
| 121 | + this.list = this.list.concat(res.items); | |
| 122 | + } | |
| 123 | + }, | |
| 124 | + async handleNotifyDetail(item, index) { | |
| 125 | + this.list[index].readStatus = 1;//点击了则说明阅读了 | |
| 126 | + await api.notifyApi.byNotifyIdGetDetailApi(item.sysNotice.id) | |
| 127 | + useNavigateTo('./notify-detail?data=', item.sysNotice) | |
| 128 | + } | |
| 129 | + } | |
| 130 | + }; | |
| 131 | +</script> | |
| 132 | + | |
| 133 | +<style lang="scss" scoped> | |
| 134 | + @import './static/systemNotify.scss'; | |
| 135 | + | |
| 136 | + /deep/ .u-badge--error { | |
| 137 | + position: relative; | |
| 138 | + right: 11rpx; | |
| 139 | + } | |
| 140 | +</style> | ... | ... |