396 lines
10 KiB
Vue
Raw Normal View History

2025-05-22 16:24:05 +08:00
<template>
<page-meta>
<navigation-bar :title="$tt('navBar.deviceList')" background-color="#007AFF">
</navigation-bar>
</page-meta>
<view class="scene-device-wrap">
<u-sticky>
<view class="nav-bar">
<view class="left-wrap">
<u-icon v-if="!isSearch" name="search" size="22" @click="isSearch = true"></u-icon>
<!-- #ifndef APP-NVUE -->
<u-input v-else v-model="queryParams.deviceName" :placeholder="$tt('product.inputDeviceName')"
shape="circle" @clear="handleClearSearch" clearable>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<u--input v-else v-model="queryParams.deviceName" :placeholder="$tt('product.inputDeviceName')"
shape="circle" @clear="handleClearSearch" clearable>
<!-- #endif -->
<template slot="prefix">
<u-icon name="search" size="22" @click="isSearch = false"></u-icon>
</template>
<template slot="suffix">
<u-button :text="$tt('timing.search')" type="primary" shape="circle" size="mini"
@click="handleSearch"></u-button>
</template>
<!-- #ifndef APP-NVUE -->
</u-input>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
</u--input>
<!-- #endif -->
</view>
<view class="right-wrap" @click="handleNextStep">{{$tt('product.next')}}</view>
</view>
<view class="tab-wrap">
<u-tabs :list="statusGroup" :scrollable="true" lineWidth="40" lineHeight="2" lineColor="transparent"
:duration="100" :activeStyle="{ fontSize: '36rpx', color: '#3c9cff', fontWeight: 'bold' }"
@change="handleStatusChange">
</u-tabs>
</view>
</u-sticky>
<view class="container-wrap">
<u-checkbox-group v-model="devices">
<view class="group-wrap">
<u-cell-group :border="false">
<view class="cell-wrap" v-for="(item,index) in list" :key="index">
<u-cell :border="false">
<view slot="title" class="slot-title">
<u--image :src="getImageUrl(item)" radius="4" width="28" height="28"></u--image>
<text class="cell-text">{{item.deviceName}}</text>
</view>
<view slot="value">
<u-checkbox :name="item.serialNumber" iconSize="16"></u-checkbox>
</view>
</u-cell>
</view>
</u-cell-group>
</view>
</u-checkbox-group>
<u-loadmore :status="loadmoreStatus" v-if="total > queryParams.pageSize"
:loading-text="$tt('scene.tryingToLoad')" :loadmoreText="$tt('scene.gentlyPullUp')"
:nomoreText="$tt('scene.emptyData')" marginTop="20" />
</view>
<view class="other">
<u-empty mode="data" :show="total === 0" marginTop="60" :text="$tt('scene.emptyData')"></u-empty>
<u-popup :show="isModel" :round="5" mode="bottom" bgColor="#eef3f7" :closeOnClickOverlay="true"
@close="isModel = false">
<view class="model-popup-wrap">
<view class="title">{{$tt('product.selectThingModel')}}</view>
<u-radio-group v-model="modelType">
<view class="cell-group-wrap">
<u-cell-group :border="false">
<view class="cell-wrap">
<u-cell :title="$tt('product.attribute')" :name="1" :border="false" isLink
@click="goToModelList"></u-cell>
</view>
<view class="cell-wrap">
<u-cell :title="$tt('product.function')" :name="2" :border="false" isLink
@click="goToModelList"></u-cell>
</view>
<view v-if="type === 'trigger'" class="cell-wrap">
<u-cell :title="$tt('product.event')" :name="3" :border="false" isLink
@click="goToModelList"></u-cell>
</view>
<view v-if="type === 'trigger'" class="cell-wrap">
<u-cell :title="$tt('sceneDetail.deviceOnline')" :border="false">
<view slot="value" class="u-slot-value">
<u-radio shape="circle" :name="5"></u-radio>
</view>
</u-cell>
</view>
<view v-if="type === 'trigger'" class="cell-wrap">
<u-cell :title="$tt('sceneDetail.Equipment')" :border="false">
<view slot="value" class="u-slot-value">
<u-radio shape="circle" :name="6"></u-radio>
</view>
</u-cell>
</view>
</u-cell-group>
</view>
</u-radio-group>
<view v-if="type === 'trigger'" class="btn">
<u-button type="primary" @click="handleConfirmMore">{{$tt('sceneDetail.complete')}}</u-button>
</view>
</view>
</u-popup>
</view>
</view>
</template>
<script>
import { listDeviceShort } from '@/apis/modules/device.js';
import { navigateBackTo } from '@/utils/common.js';
export default {
data () {
return {
type: 'trigger',
editIndex: null, // null 代表新增
isSearch: true,
isModel: false,
modelType: null, // 物模类型
// 状态列表
statusGroup: [{
id: null,
name: this.$tt('home.all')
},
{
id: 3,
name: this.$tt('home.onLine')
},
{
id: 2,
name: this.$tt('home.disabled')
},
{
id: 4,
name: this.$tt('home.offline')
},
{
id: 1,
name: this.$tt('home.notActive')
}
],
queryParams: {
productId: null,
pageNum: 1,
pageSize: 11,
deviceName: '',
status: null
},
list: [], // 产品列表
total: 0,
loadmoreStatus: 'loadmore', // 刷新和加载相关
devices: [], // 选中设备
};
},
onLoad (option) {
this.type = option.type;
const trigger = uni.getStorageSync('trigger');
const action = uni.getStorageSync('action');
if (this.type === 'trigger') {
this.queryParams.productId = trigger.productId;
} else {
this.queryParams.productId = action.productId;
}
this.getDeviceDatas();
},
methods: {
// 获取区设备列表
getDeviceDatas () {
listDeviceShort(this.queryParams)
.then(res => {
const { rows, total } = res;
this.list = this.list.concat(rows);
this.total = total;
})
.catch(err => {
console.log(err);
});
},
handleSearch () {
this.list = [];
this.queryParams.pageNum = 1;
this.getDeviceDatas();
},
handleClearSearch () {
this.handleSearch();
},
// 状态改变事件
handleStatusChange (item) {
this.list = [];
this.queryParams.status = item.id;
this.queryParams.pageNum = 1;
this.getDeviceDatas();
},
// 获取设备图片
getImageUrl (item) {
if (item.imgUrl) {
return item.imgUrl;
} else {
if (item.deviceType === 1) {
return '/static/common/device.png';
} else if (item.deviceType === 2) {
return '/static/common/gateway.png';
} else if (item.deviceType === 3) {
return '/static/common/video.png';
} else {
return '';
}
}
},
// 下拉刷新
onPullDownRefresh () {
this.list = [];
this.queryParams.pageNum = 1;
// 模拟网络请求
setTimeout(x => {
this.getDeviceDatas();
uni.stopPullDownRefresh();
}, 1000);
},
// 上拉加载
onReachBottom () {
this.loadmoreStatus = 'loading';
this.queryParams.pageNum = ++this.queryParams.pageNum;
// 模拟网络请求
setTimeout(() => {
if ((this.queryParams.pageNum - 1) * this.queryParams.pageSize >= this.total) {
this.loadmoreStatus = 'nomore';
} else {
this.loadmoreStatus = 'loading';
this.getDeviceDatas();
}
}, 1000);
},
// 下一步
handleNextStep () {
if (this.devices.length !== 0) {
this.isModel = true;
let action = uni.getStorageSync(this.type);
action = { ...action, deviceCount: this.devices.length, deviceNums: this.devices };
uni.setStorageSync(this.type, action);
} else {
uni.showToast({
icon: 'none',
title: this.$tt('product.selectDevice')
});
}
},
// 物模跳转
goToModelList ({ name }) {
let action = uni.getStorageSync(this.type);
action = { ...action, type: name, arrayIndex: '', parentId: '' };
uni.setStorageSync(this.type, action);
uni.$u.route('/pagesA/scene/product/model', { type: this.type });
},
// 选择物模
handleConfirmMore () {
if (!this.modelType) {
uni.showToast({
icon: 'none',
title: this.$tt('product.selectThingsModels')
});
return
}
let action = uni.getStorageSync(this.type);
action = { ...action, type: this.modelType };
uni.setStorageSync(this.type, action);
// 更新或者插入新的触发或者执行
let { triggers, actions, ...res } = uni.getStorageSync('sceneData');
if (Number.isNaN(this.editIndex) || this.editIndex === null) {
if (this.type === 'trigger') {
triggers.push(action);
} else {
actions.push(action);
}
uni.setStorageSync('sceneData', { triggers, actions, ...res });
} else {
if (this.type === 'trigger') {
let list = triggers.map((item, i) => {
if (i == this.editIndex) {
return action
} else {
return item
}
});
uni.setStorageSync('sceneData', { triggers: [...list], actions, ...res });
} else {
let list = actions.map((item, i) => {
if (i == this.editIndex) {
return action
} else {
return item
}
});
uni.setStorageSync('sceneData', { triggers, actions: [...list], ...res });
}
}
this.isModel = false;
uni.setStorageSync('callback', true);
navigateBackTo('/pagesA/scene/detail');
}
}
};
</script>
<style>
page {
height: 100%;
background: #eef3f7;
}
</style>
<style lang="scss" scoped>
.scene-device-wrap {
.nav-bar {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 24rpx 30rpx;
height: 74rpx;
background: #eef3f7;
.left-wrap {
flex: 1;
}
.right-wrap {
color: #3c9cff;
font-size: 28rpx;
margin-left: 20rpx;
}
}
.tab-wrap {
padding: 0rpx 10rpx;
background: #eef3f7;
}
.container-wrap {
.group-wrap {
width: 100%;
margin: 30rpx;
.cell-wrap {
background-color: #fff;
border-radius: 10rpx;
&:not(:first-child) {
margin-top: 24rpx;
}
.slot-title {
display: flex;
flex-direction: row;
align-items: center;
.cell-text {
font-size: 28rpx;
margin-left: 20rpx
}
}
}
}
}
.other {
.model-popup-wrap {
padding: 30rpx;
.title {
font-size: 32rpx;
text-align: center;
margin-bottom: 34rpx;
}
.cell-group-wrap {
width: 100%;
background: #fff;
border-radius: 10rpx;
.cell-wrap {
padding: 6rpx 0;
border-bottom: 1rpx solid #F1F2F5;
}
}
.btn {
margin-top: 30rpx;
}
}
}
}
</style>