修复普通产品没有操作列表问题

This commit is contained in:
1 2025-07-20 17:23:49 +08:00
parent c19378aa37
commit a54e2a1d5f
8 changed files with 1210 additions and 2806 deletions

52
App.vue
View File

@ -35,6 +35,8 @@
onLaunch: function() { onLaunch: function() {
console.log('App Launch'); console.log('App Launch');
// //
this.requestRecordPermission();
var isFirstOpen = uni.getStorageSync('isFirstOpen'); var isFirstOpen = uni.getStorageSync('isFirstOpen');
// isFirstOpen // isFirstOpen
if (!isFirstOpen) { if (!isFirstOpen) {
@ -115,6 +117,56 @@
} }
}); });
} }
},
//
requestRecordPermission() {
// #ifdef APP-PLUS
if (uni.getSystemInfoSync().platform === 'android') {
plus.android.requestPermissions([
'android.permission.RECORD_AUDIO'
], function(resultObj) {
let result = 0;
for (let i = 0; i < resultObj.granted.length; i++) {
result = 1;
}
for (let i = 0; i < resultObj.deniedPresent.length; i++) {
result = 0;
}
for (let i = 0; i < resultObj.deniedAlways.length; i++) {
result = -1;
}
if (result !== 1) {
uni.showModal({
title: '提示',
content: '录音权限未开启,部分功能将无法使用,请前往设置开启权限。',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
plus.runtime.openApp({
action: 'android.settings.APPLICATION_DETAILS_SETTINGS'
});
}
}
});
}
});
} else if (uni.getSystemInfoSync().platform === 'ios') {
// iOSAPI
//
const recorder = uni.getRecorderManager();
recorder.start({ duration: 1000 });
recorder.onStart(() => {
recorder.stop();
});
recorder.onError(() => {
//
uni.showModal({
title: '提示',
content: '录音权限未开启,部分功能将无法使用,请前往设置开启权限。'
});
});
}
// #endif
} }
}, },
onHide: function() { onHide: function() {

View File

@ -266,6 +266,7 @@
}; };
}, },
onLoad() { onLoad() {
this.requestRecordPermission();
this.getToken(); this.getToken();
if (this.token != '' && this.token != null) { if (this.token != '' && this.token != null) {
this.connectMqtt(); this.connectMqtt();
@ -658,6 +659,32 @@
uni.navigateTo({ uni.navigateTo({
url: '/pagesB/user/message/detail?noticeId=' + this.notices.noticeId url: '/pagesB/user/message/detail?noticeId=' + this.notices.noticeId
}); });
},
//
requestRecordPermission() {
try {
const recorder = uni.getRecorderManager();
let triggered = false;
recorder.onStart(() => {
triggered = true;
recorder.stop();
});
recorder.onError(() => {
triggered = true;
uni.showModal({
title: '提示',
content: '录音权限未开启,部分功能将无法使用,请前往设置开启权限。'
});
});
recorder.start({ duration: 1000 });
setTimeout(() => {
if (!triggered) {
recorder.stop();
}
}, 1500);
} catch (e) {
//
}
} }
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -798,21 +798,22 @@
this.deviceInfo = newVal; this.deviceInfo = newVal;
if (this.deviceInfo.deviceType != 3) { if (this.deviceInfo.deviceType != 3) {
//- //-
this.operateList = this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.filter(( this.operateList = this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.filter(
item) => (item) => String(item.isReadonly) === '0' || item.isReadonly === 0
item.isReadonly == '0'); );
this.attributeList = this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.filter(( this.attributeList = this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.filter(
item) => (item) => String(item.isReadonly) === '1' || item.isReadonly === 1
item.isReadonly == '1'); );
// //
this.attributeList = this.attributeList.sort((a, b) => b.order - a.order); this.attributeList = this.attributeList.sort((a, b) => b.order - a.order);
this.operateList = this.operateList.sort((a, b) => b.order - a.order); this.operateList = this.operateList.sort((a, b) => b.order - a.order);
} }
this.updateDeviceStatus(this.deviceInfo); this.updateDeviceStatus(this.deviceInfo);
this.initChart(); this.initChart();
console.log("wumoxing", JSON.stringify(this.deviceInfo.thingsModels)) //
console.log('【base.vue watch】deviceInfo:', JSON.stringify(this.deviceInfo));
console.log('【base.vue watch】attributeList:', JSON.stringify(this.attributeList));
console.log('【base.vue watch】operateList:', JSON.stringify(this.operateList));
} }
} }
}, },
@ -865,11 +866,27 @@
// (H5APP) // (H5APP)
if (this.device !== null && Object.keys(this.device).length !== 0) { if (this.device !== null && Object.keys(this.device).length !== 0) {
this.deviceInfo = this.device; this.deviceInfo = this.device;
if (this.deviceInfo.deviceType != 3) {
this.operateList = this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.filter(
(item) => String(item.isReadonly) === '0' || item.isReadonly === 0
);
this.attributeList = this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.filter(
(item) => String(item.isReadonly) === '1' || item.isReadonly === 1
);
//
this.attributeList = this.attributeList.sort((a, b) => b.order - a.order);
this.operateList = this.operateList.sort((a, b) => b.order - a.order);
}
this.updateDeviceStatus(this.deviceInfo); this.updateDeviceStatus(this.deviceInfo);
this.initChart(); this.initChart();
}; }
// //
this.mqttCallback(); this.mqttCallback();
//
console.log('【base.vue created】deviceInfo:', JSON.stringify(this.deviceInfo));
console.log('【base.vue created】attributeList:', JSON.stringify(this.attributeList));
console.log('【base.vue created】operateList:', JSON.stringify(this.operateList));
}, },
methods: { methods: {
/* Mqtt回调处理 */ /* Mqtt回调处理 */

View File

@ -1111,392 +1111,168 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.status-titletop {
font-weight: bold;
font-size: 15px;
color: #333333;
line-height: 42rpx;
text-align: left;
padding: 15rpx 28rpx;
background-color: #eef6ff;
border-bottom: 1rpx solid #dceaff;
}
.voice-control { .voice-control {
padding: 24rpx; padding: 32rpx;
background-color: #f5f7fa; background: #f7f9fc;
min-height: 100vh; min-height: 100vh;
font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif; font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
/* 统一卡片 */
.card { .card {
background-color: #fff; background: #fff;
border-radius: 16rpx; border-radius: 24rpx;
margin-bottom: 24rpx; margin-bottom: 32rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); box-shadow: 0 8rpx 24rpx rgba(0,0,0,.06);
overflow: hidden; overflow: hidden;
transition: all 0.3s ease; transition: all .3s ease;
&:hover { &:active { transform: scale(.99); }
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.1);
} }
/* 标题栏 */
.status-titletop {
font-size: 34rpx;
font-weight: 600;
color: #2979ff;
padding: 28rpx 40rpx;
background: linear-gradient(135deg,#e8f2ff 0%,#f0f7ff 100%);
border-bottom: 1rpx solid #dceaff;
} }
.section-title { .section-title {
font-size: 32rpx; font-size: 34rpx;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
padding: 24rpx; padding: 32rpx 40rpx;
border-bottom: 1rpx solid #f0f2f5; border-bottom: 1rpx solid #f0f2f5;
background: #fafbff;
display: flex; display: flex;
align-items: center; align-items: center;
background-color: #f9fbfd;
.add-icon { .add-icon {
width: 40rpx; width: 48rpx;
height: 40rpx; height: 48rpx;
margin-left: auto; margin-left: auto;
cursor: pointer; transition: transform .2s;
transition: transform 0.2s; &:active { transform: scale(.85); }
&:active {
transform: scale(0.9);
}
} }
} }
.info-content { /* 内容区域统一内边距 */
padding: 24rpx; .info-content { padding: 32rpx 40rpx; }
}
/* 音量控制样式 */ /* 音量滑条 */
.volume-slider { .volume-slider {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 20rpx; gap: 24rpx;
margin-bottom: 24rpx; padding: 32rpx;
padding: 20rpx; background: #f8fafc;
background-color: #f8fafc; border-radius: 20rpx;
border-radius: 12rpx; box-shadow: inset 0 0 0 1rpx #eaeef5;
border: 1rpx solid #eaeef5;
.volume-icon { .volume-icon image { width: 48rpx; height: 48rpx; }
width: 48rpx;
height: 48rpx;
display: flex;
justify-content: center;
align-items: center;
.volume-svg {
width: 100%;
height: 100%;
}
}
.slider-container { .slider-container {
flex: 1; flex: 1;
position: relative;
.volume-marks { .volume-marks {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-top: 12rpx; margin-top: 12rpx;
padding: 0 8rpx;
text {
font-size: 24rpx; font-size: 24rpx;
color: #909399; color: #909399;
font-weight: 500;
} }
} }
}
.volume-value { .volume-value {
min-width: 80rpx; min-width: 80rpx;
text-align: right; text-align: right;
font-size: 30rpx;
font-weight: 600;
color: #2979ff; color: #2979ff;
font-size: 28rpx; }
}
/* 开关行 */
.audio-switch {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
background: #f8fafc;
border-radius: 20rpx;
margin-bottom: 32rpx;
box-shadow: inset 0 0 0 1rpx #eaeef5;
font-size: 30rpx;
color: #333;
}
/* 按钮 */
.clear-screen-btn-wrap {
display: flex;
justify-content: center;
margin-top: 32rpx;
::v-deep .u-button {
width: 70%;
height: 88rpx;
font-size: 32rpx;
border-radius: 44rpx;
font-weight: 600; font-weight: 600;
} }
} }
/* 开关样式 */ /* 表单 / 列表 */
.audio-switch {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
background-color: #f8fafc;
border-radius: 12rpx;
margin-bottom: 24rpx;
border: 1rpx solid #eaeef5;
text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
}
/* 屏幕参数表单 */
.screen-params {
.screen-params-form { .screen-params-form {
padding: 20rpx 24rpx; padding: 32rpx 40rpx;
::v-deep .u-form-item { ::v-deep .u-form-item {
margin-bottom: 20rpx; margin-bottom: 24rpx;
&__body { &__body {
padding: 20rpx 0; padding: 24rpx 0;
border-bottom: 1rpx solid #f0f2f5; border-bottom: 1rpx solid #f0f2f5;
&__left { font-size: 30rpx; color: #606266; }
&__left { &__right .u-input { font-size: 30rpx; color: #333; text-align: right; }
font-size: 28rpx;
color: #606266;
font-weight: 500;
}
&__right {
.u-input {
font-size: 28rpx;
color: #333;
text-align: right;
}
}
}
} }
} }
} }
/* 列表样式 */
.audio-list,
.default-list {
.list-container { .list-container {
padding: 0 24rpx 24rpx; padding: 0 40rpx 32rpx;
}
.empty-tip { .empty-tip {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 60rpx 0; padding: 80rpx 0;
color: #c0c4cc; color: #c0c4cc;
font-size: 28rpx; font-size: 30rpx;
gap: 20rpx; gap: 24rpx;
opacity: 0.8;
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.6;
} }
}
.audio-item { .audio-item {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 24rpx 0; padding: 32rpx 0;
border-bottom: 1rpx solid #f5f5f5; border-bottom: 1rpx solid #f5f5f5;
transition: all 0.2s ease; &:last-child { border-bottom: none; }
&:last-child {
border-bottom: none;
}
&:active {
background-color: #f8f8f8;
}
.audio-info { .audio-info {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16rpx; gap: 20rpx;
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
.audio-name { .audio-name {
font-size: 28rpx; font-size: 30rpx;
color: #333; color: #333;
white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap;
} }
} }
.audio-actions { .audio-actions {
display: flex; display: flex;
align-items: center; gap: 32rpx;
gap: 24rpx;
margin-left: 16rpx;
.audio-duration {
font-size: 26rpx;
color: #909399;
} }
} }
} }
} }
/* 清除屏幕按钮 */
.clear-screen-btn-wrap {
display: flex;
justify-content: center;
margin-top: 24rpx;
::v-deep .u-button {
width: 60%;
height: 80rpx;
font-size: 28rpx;
}
}
/* 弹窗样式 */
.add-audio-modal {
width: 80vw;
max-width: 600rpx;
padding: 0;
border-radius: 16rpx;
background-color: #fff;
overflow: hidden;
.modal-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
padding: 28rpx;
text-align: center;
border-bottom: 1rpx solid #f5f5f5;
}
.modal-content {
padding: 0 28rpx;
margin: 20rpx 0;
max-height: 60vh;
overflow-y: auto;
::v-deep .u-form-item {
padding: 20rpx 0;
&__body {
padding: 0;
&__left {
width: 160rpx;
font-size: 28rpx;
color: #606266;
}
&__right {
.u-input {
font-size: 28rpx;
color: #333;
}
}
}
}
.slider-with-value {
display: flex;
align-items: center;
width: 100%;
.custom-slider {
flex: 1;
margin-right: 20rpx;
}
}
::v-deep .u-radio-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
}
.modal-footer {
display: flex;
justify-content: space-between;
padding: 16rpx 28rpx 28rpx;
border-top: 1rpx solid #f5f5f5;
.u-button {
width: 48%;
height: 80rpx;
font-size: 28rpx;
border-radius: 40rpx;
}
}
}
/* 周选择器 */
.week-picker {
display: flex;
flex-wrap: wrap;
gap: 10rpx;
padding: 10rpx 0;
.week-item {
width: 72rpx;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 36rpx;
background-color: #f5f5f5;
font-size: 28rpx;
color: #666;
transition: all 0.3s ease;
cursor: pointer;
&.active {
background-color: #2979ff;
color: #fff;
font-weight: 500;
}
}
}
/* 速度范围 */
.speed-range {
display: flex;
align-items: center;
gap: 10rpx;
.u-input {
flex: 1;
}
.separator {
color: #666;
padding: 0 10rpx;
}
.unit {
color: #666;
font-size: 26rpx;
margin-left: 10rpx;
}
}
/* 选择器值显示 */
.picker-value {
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
color: #333;
padding: 0 20rpx;
background-color: #f9f9f9;
border-radius: 8rpx;
}
/* 测试按钮 */
.test-card {
.test-buttons {
display: flex;
justify-content: space-between;
padding: 20rpx;
}
}
}
</style> </style>

View File

@ -59,16 +59,8 @@
</view> </view>
</view> </view>
</view> </view>
<u-subsection <u-subsection :list="subsectionList" :current="currentSubsection" @change="onSubsectionChange"
:list="subsectionList" activeColor="#2979ff" inactiveColor="#666" :fontSize="14" :height="80" :bold="true" mode="subsection" :animation="true"
:current="currentSubsection"
@change="onSubsectionChange"
activeColor="#2979ff"
inactiveColor="#666"
:fontSize="28"
:height="80"
:bold="true"
:styleType="'button'"
></u-subsection> ></u-subsection>
</view> </view>
@ -83,6 +75,13 @@
<view v-if="currentSubsection === 1" class="subdevice-panel"> <view v-if="currentSubsection === 1" class="subdevice-panel">
<display-control :device="device"></display-control> <display-control :device="device"></display-control>
</view> </view>
<view v-if="currentSubsection === 2" class="subdevice-panel">
<gatewayset :device="device"></gatewayset>
</view>
</view> </view>
</view> </view>
</template> </template>
@ -90,12 +89,13 @@
<script> <script>
import VoiceControl from './voice.vue'; import VoiceControl from './voice.vue';
import DisplayControl from './display.vue'; import DisplayControl from './display.vue';
import gatewayset from './gatewayset.vue';
export default { export default {
name: 'GatewayControl', name: 'GatewayControl',
components: { components: {
VoiceControl, VoiceControl,
DisplayControl DisplayControl,
gatewayset
}, },
props: { props: {
device: { device: {
@ -109,14 +109,19 @@ export default {
currentSubsection: 0, currentSubsection: 0,
subsectionList: [ subsectionList: [
{ {
text: '声卡', name: '声卡',
icon: 'volume', icon: 'volume',
description: '音频控制' description: '音频控制'
}, },
{ {
text: '显卡', name: '显卡',
icon: 'eye', icon: 'eye',
description: '显示控制' description: '显示控制'
},
{
name: '网关',
icon: 'eye',
description: '网关控制'
} }
], ],
deviceInfo: { deviceInfo: {

File diff suppressed because it is too large Load Diff

View File

@ -8,29 +8,29 @@
<u--text iconStyle="color: #486ff2; margin-right: 4px; font-size: 22px;" type="primary" <u--text iconStyle="color: #486ff2; margin-right: 4px; font-size: 22px;" type="primary"
prefixIcon="list-dot" align="right" text="设备详情" @click="handleGoToDeviceDetail"></u--text> prefixIcon="list-dot" align="right" text="设备详情" @click="handleGoToDeviceDetail"></u--text>
</view> </view>
<view class="running-status" <view v-if="isRelayProduct">
v-if="current==0 && !isRelayProduct && !isVoiceProduct && !isGatewayProduct&&!isdisplay">
<base-status :device="device" ref="baseStatus"></base-status>
</view>
<view class="deviceVariable"
v-if="current==1 && !isRelayProduct && !isVoiceProduct && !isGatewayProduct&&!isdisplay">
<device-variable ref="deviceVariable" :device="device"></device-variable>
</view>
<view class="relay-control" v-if="isRelayProduct">
<relay-control :device="device" ref="relayControl"></relay-control> <relay-control :device="device" ref="relayControl"></relay-control>
</view> </view>
<view class="voice-control" v-if="isVoiceProduct"> <view v-else-if="isVoiceProduct">
<voice :device="device" ref="voice"></voice> <voice :device="device" ref="voice"></voice>
</view> </view>
<!-- <view class="relay-control" v-show="isRelayProduct"> <view v-else-if="isGatewayProduct">
<GRelay :device="device" ref="GRelay"></GRelay>
</view> -->
<view class="gateway" v-if="isGatewayProduct">
<gateway :device="device" ref="gateway"></gateway> <gateway :device="device" ref="gateway"></gateway>
</view> </view>
<view class="display" v-if="isdisplay"> <view v-else-if="isdisplay">
<display :device="device" ref="display"></display> <display :device="device" ref="display"></display>
</view> </view>
<view v-else>
<view v-if="current==0">
<base-status :device="device" ref="baseStatus"></base-status>
</view>
<view v-else-if="current==1">
<device-variable ref="deviceVariable" :device="device"></device-variable>
</view>
<view v-else>
暂无数据
</view>
</view>
</view> </view>
</template> </template>