Commit b61a66a929c5e0f5dc25a636d917884dfb44d880

Authored by fengtao
1 parent 04938137

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

1 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 32 </template>
4 33
5 34 <script>
  35 + import {
  36 + useShowModal
  37 + } from '@/plugins/utils.js'
  38 +
6 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>
\ No newline at end of file
  114 +</style>
\ No newline at end of file
... ...
... ... @@ -6,23 +6,25 @@
6 6 <view class="basic-header">
7 7 <view class="u-flex">
8 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 10 </view>
12 11 <view class="basic-text text-clip ml-2">
13   - {{ deviceDetail.alias? deviceDetail.alias: deviceDetail.name }}
  12 + {{ deviceDetail.alias ? deviceDetail.alias : deviceDetail.name }}
14 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 15 {{ deviceStatus }}
17 16 </view>
18 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 21 <!-- #ifdef MP -->
22 22 <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="handleMpShowModal" />
23 23 <!-- #endif -->
24 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 28 <!-- #endif -->
27 29 </view>
28 30 </view>
... ... @@ -60,201 +62,205 @@
60 62 </view>
61 63 <!-- 命令下发 -->
62 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 71 <!-- #endif -->
65 72 <!-- #ifdef MP -->
66 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 81 <!-- #endif -->
70 82 </view>
71 83 </template>
72 84
73 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 198 </script>
194 199
195 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>
\ No newline at end of file
  263 +/deep/ .u-modal__content {
  264 + padding: 30rpx 0 !important;
  265 +}
  266 +</style>
... ...
  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
... ...