2025-05-22 16:24:05 +08:00

496 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<page-meta>
<navigation-bar :title="$tt('scene.sceneLink')" title-align="center" background-color="#007AFF" />
</page-meta>
<view class="scene-wrap">
<u-sticky zIndex="98" bgColor="#eef3f7">
<view class="nav-bar">
<view class="left-wrap">
<view style="margin-right: 20rpx;">
<u-icon name="list-dot" size="23" @click="isMenu = true"></u-icon>
</view>
<view v-if="!isSearch" style="margin-right: 20rpx;">
<u-icon name="search" size="23" @click="isSearch = true"></u-icon>
</view>
<view v-else style="margin-right: 20rpx; width: 100%;">
<!-- #ifndef APP-NVUE -->
<u-input :customStyle="{ padding: '6rpx 18rpx'}" v-model="queryParams.sceneName"
:placeholder="$tt('scene.inputSceneName')" shape="circle" @clear="handleClearSearch"
clearable>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<u--input :customStyle="{ padding: '6rpx 18rpx'}" v-model="queryParams.sceneName"
:placeholder="$tt('scene.inputSceneName')" 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('scene.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>
<u-icon name="plus-circle-fill" size="23" color='#3c9cff' bold @tap="handleAddScene"></u-icon>
</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">
<view class="item-wrap" v-for="(item, index) in list" :key="index">
<view class="card" :style="{ margin: index === 0 ? '0 30rpx 30rpx' : '30rpx'}">
<view class="delIcon" @click="handleDelete(item)">
<u-icon size="18" name="close-circle-fill" color="#007aff"></u-icon>
</view>
<view @click="handleSceneDetail(item.sceneId)">
<view class="title">
<u--text lines="1" :text="item.sceneName"></u--text>
<u-icon name="arrow-right" color="#606266" customStyle="margin-right:5px;"
size="14"></u-icon>
</view>
<view class="cond">{{$tt('scene.condition')}}{{getCondName(item.cond)}}</view>
<view class="cond">{{$tt('scene.way')}}{{getExecuteModeName(item.executeMode)}}</view>
<view class="cond">{{$tt('scene.task')}}{{item.actionCount}}个</view>
<view class="bottom-wrap" @tap.stop>
<u--text lines="1" prefixIcon="/static/scene/once.png"
iconStyle="width: 14px;height: 14px;margin-right: 3px;" size="13"
:text="$tt('scene.execute')" color='#3C9CFF' lineHeight="16"
@click="handleRunOnce(item)"></u--text>
<u-switch v-model="item.enable" @change="handleSwitchStatus(item)" :activeValue="1"
:inactiveValue="2" activeColor="#3C9CFF" inactiveColor="#dbdbdb" size="18"></u-switch>
</view>
</view>
</view>
</view>
<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="isMenu" mode="top" :closeOnClickOverlay="true" :round="5" @close="isMenu = false">
<view class="menu-popup-wrap">
<view class="group-wrap">
<u-cell-group :border="false">
<view class="cell-wrap">
<u-cell icon="grid" :title="$tt('scene.administration')" :border="false" isLink
@click="goToSceneList"></u-cell>
</view>
</u-cell-group>
</view>
</view>
</u-popup>
</view>
<u-modal :show="isDelete" showCancelButton :confirmText="$tt('common.delete')" @cancel="() => isDelete = false"
:title="$tt('sceneDetail.tips')" :content="deleteContent" @confirm="handleConfirmDelete">
</u-modal>
</view>
</template>
<script>
import {
listScene,
runScene,
updateStatus,
delScene
} from '@/apis/modules/scene';
export default {
beforeRouteEnter(to, from, next) {
// 在进入路由前执行一些操作,例如加载数据等
next(vm => {
// 这里可以访问组件实例 `vm`
vm.onLoad() // 执行加载操作
})
},
data() {
return {
deleteId: '',
isDelete: false,
deleteContent: '',
isMenu: false,
isSearch: true,
// 状态列表
statusGroup: [{
id: null,
name: this.$tt('timing.all')
},
{
id: 1,
name: this.$tt('timing.enable')
},
{
id: 2,
name: this.$tt('timing.notEnabled')
}
],
queryParams: {
pageNum: 1,
pageSize: 4,
enable: null,
sceneName: '',
},
list: [],
total: 0,
loadmoreStatus: 'loadmore', // 刷新和加载相关
};
},
onLoad() {
this.getToken();
if (this.token != '' && this.token != null) {
this.getList();
}
},
onShow() {
// #ifdef MP-WEIXIN
// 检查用户是否登录
if (!this.isLogin()) {
uni.showModal({
title: '提示',
content: '您还未登录,请登录后查看',
success: (res) => {
if (res.confirm) {
// 用户点击确定,跳转到登录页面
uni.navigateTo({
url: '/pages/login/index'
});
} else if (res.cancel) {
uni.switchTab({
url: '/pages/tabBar/home/index'
})
console.log('用户点击取消');
}
}
});
}
// #endif
},
methods: {
getToken() {
// 本地缓存获取token
this.token = uni.getStorageSync('token');
// vuex存储token
uni.$u.vuex('vuex_token', this.token);
console.log(this.token)
},
//删除
handleDelete(item) {
this.isDelete = true;
this.deleteId = item.sceneId;
this.deleteContent = `确定删除“${item.sceneName}”?`
},
// 确认删除
handleConfirmDelete() {
delScene(this.deleteId).then(res => {
if (res.code === 200) {
this.list = [];
this.queryParams.pageNum = 1;
this.getList();
} else {
uni.showToast({
icon: 'none',
title: res.msg
});
}
this.isDelete = false;
}).catch(e => {
console.log(e);
});
},
//判断是否登录
isLogin() {
if (this.token == '' || this.token == null) {
return false;
} else {
return true;
}
},
// 场景状态改变事件
handleStatusChange(item) {
this.list = [];
this.queryParams.enable = item.id;
this.queryParams.pageNum = 1;
this.getList();
},
// 场景列表
goToSceneList() {
uni.navigateTo({
url: '/pagesA/scene/list'
});
this.isMenu = false;
},
// 新增场景
handleAddScene() {
// 使用vuex会导致小程序性能问题所以存储本地
let sceneData = {
sceneId: null,
sceneName: '',
remark: '',
enable: 1, // 状态1启动2暂停
cond: 1, // 触发条件1任意条件2所有条件3不满足
silentPeriod: 0, // 静默时间
executeMode: 1, // 执行方式1串行2并行
executeDelay: 0, // 延时执行
hasAlert: 2, // 1包含告警2不包含告警
applicationName: 'fastbee', // 固定值
triggers: [],
actions: [],
};
const storage = uni.getStorageSync('sceneData');
if (storage) {
uni.removeStorageSync('sceneData');
}
uni.setStorageSync('sceneData', sceneData);
uni.removeStorageSync('callback');
uni.navigateTo({
url: '/pagesA/scene/detail'
});
},
// 场景详情
handleSceneDetail(id) {
const storage = uni.getStorageSync('sceneData');
if (storage) {
uni.removeStorageSync('sceneData');
}
const sceneData = {
sceneId: null,
sceneName: '',
remark: '',
enable: 1, // 状态1启动2暂停
cond: 1, // 触发条件1任意条件2所有条件3不满足
silentPeriod: 0, // 静默时间
executeMode: 1, // 执行方式1串行2并行
executeDelay: 0, // 延时执行
hasAlert: 2, // 1包含告警2不包含告警
applicationName: 'fastbee', // 固定值
triggers: [],
actions: [],
};
uni.setStorageSync('sceneData', sceneData);
uni.removeStorageSync('callback');
uni.navigateTo({
url: '/pagesA/scene/detail?sceneId=' + id
});
},
// 获取条件
getCondName(cond) {
if (cond === 1) {
return this.$tt('scene.anyCondition')
} else if (cond === 2) {
return this.$tt('scene.allCondition')
} else if (cond === 3) {
return this.$tt('scene.notConditions')
} else {
return this.$tt('scene.unknown')
}
},
getExecuteModeName(mode) {
if (mode === 1) {
return this.$tt('scene.serial')
} else if (mode === 2) {
return this.$tt('scene.parallel')
} else {
return this.$tt('scene.unknown')
}
},
// 获取场景列表
getList() {
listScene(this.queryParams)
.then(res => {
const {
rows,
total
} = res;
this.list = this.list.concat(rows);
this.total = total;
console.log(rows, '场景联动列表');
})
.catch(err => {
console.log(err);
});
},
// 搜索
handleSearch() {
this.list = [];
this.queryParams.pageNum = 1;
this.getList();
},
handleClearSearch() {
this.handleSearch();
},
// 下拉刷新
onPullDownRefresh() {
console.log('下拉刷新');
this.list = [];
this.total = 0;
this.queryParams.pageNum = 1;
// 模拟网络请求
setTimeout(x => {
this.getList();
uni.stopPullDownRefresh();
}, 1000);
},
// 上拉加载
onReachBottom() {
console.log('上拉加载');
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.getList();
}
}, 1000);
},
//执行一次
handleRunOnce(data) {
const params = {
sceneId: data.sceneId
};
runScene(params).then((res) => {
uni.showToast({
icon: 'none',
title: res.msg
});
});
},
// 切换状态
handleSwitchStatus(data) {
const params = {
sceneId: data.sceneId,
enable: data.enable,
}
updateStatus(params).then((res) => {
if (res.code === 200) {
uni.showToast({
icon: 'none',
title: this.$tt('scene.switchSuccessful')
});
} else {
uni.showToast({
icon: 'none',
title: this.$tt('scene.switchFail')
});
}
});
},
}
};
</script>
<style>
page {
height: 100%;
background: #eef3f7;
}
</style>
<style lang="scss" scoped>
.scene-wrap {
.nav-bar {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 24rpx 26rpx 0;
height: 74rpx;
.left-wrap {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
}
}
.tab-wrap {
padding: 0 12rpx 10rpx 12rpx;
.add-btn {
padding: 0 20rpx;
}
}
.container-wrap {
margin-top: 20rpx;
padding-bottom: 120rpx;
.item-wrap {
.card {
position: relative;
box-shadow: 0 2rpx 0rpx 0 rgba(0, 0, 0, 0.1);
border-radius: 20rpx;
padding: 30rpx;
background-color: #fff;
.title {
padding: 10rpx 0;
display: flex;
flex-direction: row;
}
.cond {
font-size: 12px;
color: #7e7e7e;
margin-top: 10rpx;
}
.bottom-wrap {
display: flex;
flex-direction: row;
padding: 20rpx 0 10rpx;
}
.delIcon {
position: absolute;
top: -10rpx;
right: -10rpx;
cursor: pointer;
}
}
}
}
.other {
.menu-popup-wrap {
.group-wrap {
background-color: #fff;
border-radius: 10rpx;
.cell-wrap {
padding: 6rpx 0;
&:not(:last-child) {
border-bottom: 1rpx solid #F1F2F5;
}
}
}
}
// 小程序中popup坑
::v-deep .u-safe-bottom {
display: none;
}
}
}
</style>