Commit b61a66a929c5e0f5dc25a636d917884dfb44d880

Authored by fengtao
1 parent 04938137

pref: 优化app端下发命令弹窗

1 <template> 1 <template>
2 - 2 + <view class="w-100 modal-content">
  3 + <view class="header-title">命令下发</view>
  4 + <view class="u-flex">
  5 + <text class="type-text">下发类型:</text>
  6 + <u-radio-group v-model="commandType" placement="row">
  7 + <u-radio activeColor="#3388FF" label="单向" name="OneWay"></u-radio>
  8 + <view style="margin: 0 20rpx;"></view>
  9 + <u-radio activeColor="#3388FF" label="双向" name="TwoWay"></u-radio>
  10 + </u-radio-group>
  11 + </view>
  12 + <view class="content-body">
  13 + <div class="u-flex u-row-between">
  14 + <u--textarea :placeholder="`请输入下发内容${isShowTCP?'(字符串格式)':'(json格式)'}`"
  15 + v-model="inputCommandVal" />
  16 + <u-icon v-if="!isShowTCP" @click="handleCopy(copyTextValue)" name="question-circle"
  17 + color="#2979ff" size="28" class="ml-10">
  18 + </u-icon>
  19 +
  20 + </div>
  21 + </view>
  22 + <view class="button-group">
  23 + <view>
  24 + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="取消"
  25 + @click="cancelCommand"></u-button>
  26 + </view>
  27 + <view>
  28 + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmCommand"></u-button>
  29 + </view>
  30 + </view>
  31 + </view>
3 </template> 32 </template>
4 33
5 <script> 34 <script>
  35 + import {
  36 + useShowModal
  37 + } from '@/plugins/utils.js'
  38 +
6 export default { 39 export default {
  40 + props: {
  41 + isShowTCP: Boolean
  42 + },
  43 + data() {
  44 + return {
  45 + current: 0,
  46 + commandType: 'OneWay',
  47 + inputCommandVal: '',
  48 + copyTextValue: {
  49 + "method": "methodThingskit",
  50 + "params": {
  51 + "pin": 7,
  52 + "value": 1
  53 + }
  54 + }
  55 + }
  56 + },
  57 + methods: {
  58 + cancelCommand() {
  59 + this.$emit('cancelCommand')
  60 + },
  61 + confirmCommand() {
  62 + this.$emit('confirmCommand', this.commandType, this.inputCommandVal)
  63 + },
  64 + handleCopy(value) {
  65 + useShowModal(JSON.stringify(value), '命令下发', '复制内容').then(res => {
  66 + uni.setClipboardData({
  67 + data: JSON.stringify(value),
  68 + success: () => {
  69 + uni.showToast({
  70 + title: '复制成功'
  71 + })
  72 + }
  73 + });
  74 + })
  75 + }
  76 + }
  77 + }
  78 +</script>
  79 +
  80 +<style lang="scss" scoped>
  81 + .modal-content {
  82 + width: 720rpx;
  83 + padding: 0 30rpx;
  84 + background-color: white;
  85 +
  86 + .header-title {
  87 + text-align: center;
  88 + font-weight: 700;
  89 + margin-bottom: 40rpx;
  90 + }
  91 +
  92 + .type-text {
  93 + color: #333;
  94 + font-size: 14px;
  95 + font-weight: 700;
  96 + margin-right: 30rpx;
  97 + }
  98 +
  99 + .content-body {
  100 + margin-top: 28rpx;
  101 + width: 100%;
  102 + }
  103 +
  104 + .button-group {
  105 + display: flex;
  106 + margin-top: 40rpx;
  107 + justify-content: space-between;
7 108
  109 + view {
  110 + width: 300rpx;
  111 + }
  112 + }
8 } 113 }
9 -</script>  
  114 +</style>
@@ -6,23 +6,25 @@ @@ -6,23 +6,25 @@
6 <view class="basic-header"> 6 <view class="basic-header">
7 <view class="u-flex"> 7 <view class="u-flex">
8 <view class="pl-3"> 8 <view class="pl-3">
9 - <u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick" name="map-fill">  
10 - </u-icon> 9 + <u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick" name="map-fill"></u-icon>
11 </view> 10 </view>
12 <view class="basic-text text-clip ml-2"> 11 <view class="basic-text text-clip ml-2">
13 - {{ deviceDetail.alias? deviceDetail.alias: deviceDetail.name }} 12 + {{ deviceDetail.alias ? deviceDetail.alias : deviceDetail.name }}
14 </view> 13 </view>
15 - <view class="basic-text-status ml-2" :style="{ color: formatTextStatus(deviceDetail.deviceState)}"> 14 + <view class="basic-text-status ml-2" :style="{ color: formatTextStatus(deviceDetail.deviceState) }">
16 {{ deviceStatus }} 15 {{ deviceStatus }}
17 </view> 16 </view>
18 </view> 17 </view>
19 <!-- 命令下发 设备在线并且不是网关子设备 --> 18 <!-- 命令下发 设备在线并且不是网关子设备 -->
20 - <view class="mr-2" v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.deviceType !== 'SENSOR'"> 19 + <!-- v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.deviceType !== 'SENSOR'" -->
  20 + <view class="mr-2">
21 <!-- #ifdef MP --> 21 <!-- #ifdef MP -->
22 <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="handleMpShowModal" /> 22 <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="handleMpShowModal" />
23 <!-- #endif --> 23 <!-- #endif -->
24 <!-- #ifdef APP-PLUS --> 24 <!-- #ifdef APP-PLUS -->
25 - <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="handleAppShowModal" /> 25 + <view @tap="handleAppShowModal" data-target="Modal">
  26 + <text>下发命令</text>
  27 + </view>
26 <!-- #endif --> 28 <!-- #endif -->
27 </view> 29 </view>
28 </view> 30 </view>
@@ -60,201 +62,205 @@ @@ -60,201 +62,205 @@
60 </view> 62 </view>
61 <!-- 命令下发 --> 63 <!-- 命令下发 -->
62 <!-- #ifdef APP-PLUS --> 64 <!-- #ifdef APP-PLUS -->
63 - <app-command-issuance></app-command-issuance> 65 + <!-- 原生弹窗 -->
  66 + <view class="cu-modal" :class="modalName == 'Modal' ? 'show' : ''">
  67 + <view class="cu-dialog" style="padding: 300rpx 0 70rpx">
  68 + <app-command-issuance :isShowTCP="isShowTCP" @hideModal="hideMpModal" @cancelCommand="cancelCommand" @confirmCommand="confirmCommand"></app-command-issuance>
  69 + </view>
  70 + </view>
64 <!-- #endif --> 71 <!-- #endif -->
65 <!-- #ifdef MP --> 72 <!-- #ifdef MP -->
66 <!-- u-modal在app端弹窗层级无法覆盖 --> 73 <!-- u-modal在app端弹窗层级无法覆盖 -->
67 - <mp-command-issuance :isShowTCP="isShowTCP" :showModal="mpShowModal" @hideModal="hideMpModal"  
68 - @cancelCommand="cancelCommand" @confirmCommand="confirmCommand"></mp-command-issuance> 74 + <mp-command-issuance
  75 + :isShowTCP="isShowTCP"
  76 + :showModal="mpShowModal"
  77 + @hideModal="hideMpModal"
  78 + @cancelCommand="cancelCommand"
  79 + @confirmCommand="confirmCommand"
  80 + ></mp-command-issuance>
69 <!-- #endif --> 81 <!-- #endif -->
70 </view> 82 </view>
71 </template> 83 </template>
72 84
73 <script> 85 <script>
74 - import {  
75 - formatToDate  
76 - } from '@/plugins/utils.js';  
77 - import {  
78 - issueCommand  
79 - } from '../api/index.js';  
80 - import api from '@/api/index.js'  
81 - import mpCommandIssuance from './mp-command-issuance.vue'  
82 - import appCommandIssuance from './app-command-issuance.vue' 86 +import { formatToDate } from '@/plugins/utils.js';
  87 +import { issueCommand } from '../api/index.js';
  88 +import api from '@/api/index.js';
  89 +import mpCommandIssuance from './mp-command-issuance.vue';
  90 +import appCommandIssuance from './app-command-issuance.vue';
83 91
84 - export default {  
85 - components: {  
86 - mpCommandIssuance,  
87 - appCommandIssuance, 92 +export default {
  93 + components: {
  94 + mpCommandIssuance,
  95 + appCommandIssuance
  96 + },
  97 + props: {
  98 + deviceDetail: {
  99 + type: Object,
  100 + default: () => ({})
  101 + }
  102 + },
  103 + data() {
  104 + return {
  105 + mpShowModal: false,
  106 + commandValue: {},
  107 + isShowTCP: false, //用于下发命令时判断是否是TCP/UDP
  108 + modalName: null
  109 + };
  110 + },
  111 + computed: {
  112 + deviceStatus() {
  113 + return this.deviceDetail.deviceState === 'INACTIVE' ? '待激活' : this.deviceDetail.deviceState === 'ONLINE' ? '在线' : '离线';
88 }, 114 },
89 - props: {  
90 - deviceDetail: {  
91 - type: Object,  
92 - default: () => ({})  
93 - } 115 + deviceType() {
  116 + return this.deviceDetail.deviceType === 'DIRECT_CONNECTION'
  117 + ? '直连设备'
  118 + : this.deviceDetail.deviceType === 'GATEWAY'
  119 + ? '网关设备'
  120 + : this.deviceDetail.deviceType === 'SENSOR'
  121 + ? '网关子设备'
  122 + : '';
  123 + },
  124 + alarmStatus() {
  125 + return this.deviceDetail.alarmStatus === '0' ? '否' : '是';
  126 + },
  127 + formatLastOnlineTime() {
  128 + return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss');
  129 + }
  130 + },
  131 + onLoad() {
  132 + // 隐藏原生的tabbar
  133 + uni.hideTabBar();
  134 + },
  135 + methods: {
  136 + formatTextStatus(deviceState) {
  137 + return deviceState === 'INACTIVE' ? '#666' : deviceState === 'ONLINE' ? '#377DFF' : '#DE4437';
94 }, 138 },
95 - data() {  
96 - return {  
97 - mpShowModal: false,  
98 - appShowModal: false,  
99 - commandValue: {},  
100 - isShowTCP: false, //用于下发命令时判断是否是TCP/UDP 139 + handleClick() {
  140 + const data = {
  141 + longitude: this.deviceDetail.deviceInfo.longitude || 0,
  142 + latitude: this.deviceDetail.deviceInfo.latitude || 0
101 }; 143 };
  144 + uni.navigateTo({
  145 + url: '/device-subpackage/device-detail/device-position?data=' + JSON.stringify(data)
  146 + });
102 }, 147 },
103 - computed: {  
104 - deviceStatus() {  
105 - return this.deviceDetail.deviceState === 'INACTIVE' ? '待激活' : this.deviceDetail.deviceState === 'ONLINE' ?  
106 - '在线' : '离线'  
107 - },  
108 - deviceType() {  
109 - return this.deviceDetail.deviceType === 'DIRECT_CONNECTION' ?  
110 - '直连设备' :  
111 - this.deviceDetail.deviceType === 'GATEWAY' ?  
112 - '网关设备' :  
113 - this.deviceDetail.deviceType === 'SENSOR' ?  
114 - '网关子设备' :  
115 - '';  
116 - },  
117 - alarmStatus() {  
118 - return this.deviceDetail.alarmStatus === '0' ? '否' : '是';  
119 - },  
120 - formatLastOnlineTime() {  
121 - return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss');  
122 - } 148 + disabledScroll() {
  149 + return;
123 }, 150 },
124 - onLoad() {  
125 - // 隐藏原生的tabbar  
126 - uni.hideTabBar(); 151 + handleAppShowModal(e) {
  152 + this.modalName = e.currentTarget.dataset.target;
127 }, 153 },
128 - methods: {  
129 - formatTextStatus(deviceState) {  
130 - return deviceState === 'INACTIVE' ? '#666' : deviceState === 'ONLINE' ? '#377DFF' : '#DE4437'  
131 - },  
132 - handleClick() {  
133 - const data = {  
134 - longitude: this.deviceDetail.deviceInfo.longitude || 0,  
135 - latitude: this.deviceDetail.deviceInfo.latitude || 0  
136 - };  
137 - uni.navigateTo({  
138 - url: '/device-subpackage/device-detail/device-position?data=' + JSON.stringify(data)  
139 - });  
140 - },  
141 - disabledScroll() {  
142 - return;  
143 - },  
144 - handleAppShowModal() {  
145 - this.appShowModal = true  
146 - this.$refs.appCommandIssuanceRef.open()  
147 - },  
148 - handleMpShowModal() {  
149 - const {  
150 - transportType  
151 - } = this.deviceDetail.deviceProfile  
152 - this.isShowTCP = transportType == 'TCP' ? true : false  
153 - this.mpShowModal = true;  
154 - },  
155 - hideMpModal() {  
156 - this.mpShowModal = false;  
157 - },  
158 - hideAppModal() {  
159 - this.appShowModal = false  
160 - },  
161 - async confirmCommand(commandType, inputCommandVal) {  
162 - try {  
163 - if (this.isShowTCP) { //TCP的格式只能是字符串  
164 - const zg = /^[0-9a-zA-Z]*$/  
165 - if (!zg.test(inputCommandVal)) {  
166 - uni.$u.toast('输入的内容只能是字母和数字的组合')  
167 - return  
168 - }  
169 - this.commandValue.params = inputCommandVal  
170 - } else {  
171 - this.commandValue.params = JSON.parse(inputCommandVal); 154 + handleMpShowModal() {
  155 + const { transportType } = this.deviceDetail.deviceProfile;
  156 + this.isShowTCP = transportType == 'TCP' ? true : false;
  157 + this.mpShowModal = true;
  158 + },
  159 + hideMpModal() {
  160 + this.mpShowModal = false;
  161 + },
  162 + hideAppModal() {
  163 + this.modalName = null;
  164 + },
  165 + async confirmCommand(commandType, inputCommandVal) {
  166 + try {
  167 + if (this.isShowTCP) {
  168 + //TCP的格式只能是字符串
  169 + const zg = /^[0-9a-zA-Z]*$/;
  170 + if (!zg.test(inputCommandVal)) {
  171 + uni.$u.toast('输入的内容只能是字母和数字的组合');
  172 + return;
172 } 173 }
173 - if (!commandJsonValue) return uni.$u.toast('请输入下发内容~');  
174 - this.commandValue.persistent = true;  
175 - this.commandValue.additionalInfo = {  
176 - cmdType: 'API'  
177 - };  
178 - this.commandValue.method = 'methodThingskit';  
179 - this.commandValue.params = commandJsonValue  
180 - await api.deviceApi.issueCommand(commandType, this.deviceDetail.tbDeviceId, this.commandValue);  
181 - this.cancelCommand();  
182 - uni.$u.toast('下发成功~');  
183 - } catch (e) {  
184 - uni.$u.toast('下发失败~'); 174 + this.commandValue.params = inputCommandVal;
  175 + } else {
  176 + this.commandValue.params = JSON.parse(inputCommandVal);
185 } 177 }
186 - },  
187 - cancelCommand() {  
188 - this.hideMpModal();  
189 - this.hideAppModal() 178 + if (!commandJsonValue) return uni.$u.toast('请输入下发内容~');
  179 + this.commandValue.persistent = true;
  180 + this.commandValue.additionalInfo = {
  181 + cmdType: 'API'
  182 + };
  183 + this.commandValue.method = 'methodThingskit';
  184 + this.commandValue.params = commandJsonValue;
  185 + await api.deviceApi.issueCommand(commandType, this.deviceDetail.tbDeviceId, this.commandValue);
  186 + this.cancelCommand();
  187 + uni.$u.toast('下发成功~');
  188 + } catch (e) {
  189 + uni.$u.toast('下发失败~');
190 } 190 }
  191 + },
  192 + cancelCommand() {
  193 + this.hideMpModal();
  194 + this.hideAppModal();
191 } 195 }
192 - }; 196 + }
  197 +};
193 </script> 198 </script>
194 199
195 <style lang="scss" scoped> 200 <style lang="scss" scoped>
196 - .basic-page {  
197 - padding: 0 30rpx; 201 +@import url('../static/modal.css');
  202 +.basic-page {
  203 + padding: 0 30rpx;
198 204
199 - .basic-header {  
200 - display: flex;  
201 - justify-content: space-between;  
202 - align-items: center;  
203 - height: 140rpx;  
204 - background-color: #fff;  
205 - border-radius: 20rpx; 205 + .basic-header {
  206 + display: flex;
  207 + justify-content: space-between;
  208 + align-items: center;
  209 + height: 140rpx;
  210 + background-color: #fff;
  211 + border-radius: 20rpx;
206 212
207 - .basic-text {  
208 - width: 370rpx;  
209 - } 213 + .basic-text {
  214 + width: 370rpx;
  215 + }
210 216
211 - .cu-item {  
212 - background: #3388FF;  
213 - border-radius: 12px;  
214 - width: 120rpx;  
215 - height: 48rpx;  
216 - text-align: center;  
217 - line-height: 40rpx; 217 + .cu-item {
  218 + background: #3388ff;
  219 + border-radius: 12px;
  220 + width: 120rpx;
  221 + height: 48rpx;
  222 + text-align: center;
  223 + line-height: 40rpx;
218 224
219 - text {  
220 - font-size: 12px;  
221 - font-family: PingFangSC-Regular, PingFang SC;  
222 - font-weight: 400;  
223 - color: #FFFFFF;  
224 - } 225 + text {
  226 + font-size: 12px;
  227 + font-family: PingFangSC-Regular, PingFang SC;
  228 + font-weight: 400;
  229 + color: #ffffff;
225 } 230 }
  231 + }
226 232
227 - .basic-text-status {  
228 - font-size: 14px;  
229 - } 233 + .basic-text-status {
  234 + font-size: 14px;
230 } 235 }
  236 + }
231 237
232 - .detail {  
233 - background-color: #fff;  
234 - margin-top: 30rpx;  
235 - border-radius: 20rpx;  
236 - width: 690rpx; 238 + .detail {
  239 + background-color: #fff;
  240 + margin-top: 30rpx;
  241 + border-radius: 20rpx;
  242 + width: 690rpx;
237 243
238 - .detail-item {  
239 - padding: 30rpx;  
240 - display: flex;  
241 - align-items: center; 244 + .detail-item {
  245 + padding: 30rpx;
  246 + display: flex;
  247 + align-items: center;
242 248
243 - .detail-label {  
244 - color: #333;  
245 - font-size: 15px;  
246 - } 249 + .detail-label {
  250 + color: #333;
  251 + font-size: 15px;
  252 + }
247 253
248 - .detail-value {  
249 - color: #666;  
250 - font-size: 14px;  
251 - margin-left: 30rpx;  
252 - } 254 + .detail-value {
  255 + color: #666;
  256 + font-size: 14px;
  257 + margin-left: 30rpx;
253 } 258 }
254 } 259 }
255 } 260 }
  261 +}
256 262
257 - /deep/ .u-modal__content {  
258 - padding: 30rpx 0 !important;  
259 - }  
260 -</style>  
  263 +/deep/ .u-modal__content {
  264 + padding: 30rpx 0 !important;
  265 +}
  266 +</style>
  1 +/* ==================
  2 +模态窗口 采用colorsui的部分样式
  3 +==================== */
  4 +
1 .cu-modal { 5 .cu-modal {
2 position: fixed; 6 position: fixed;
3 top: 0; 7 top: 0;
@@ -18,7 +22,7 @@ @@ -18,7 +22,7 @@
18 } 22 }
19 23
20 .cu-modal::before { 24 .cu-modal::before {
21 - content: "\200B"; 25 + content: '\200B';
22 display: inline-block; 26 display: inline-block;
23 height: 100%; 27 height: 100%;
24 vertical-align: middle; 28 vertical-align: middle;
@@ -89,8 +93,8 @@ @@ -89,8 +93,8 @@
89 transform: translateX(0%); 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 min-width: 100rpx; 97 min-width: 100rpx;
94 margin-right: 0; 98 margin-right: 0;
95 min-height: 100rpx; 99 min-height: 100rpx;
96 -} 100 +}