smart-power-ui/src/views/iot/project/profileV2/ESceneManage/index.vue

739 lines
20 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>
<div class="e-scene-manage">
<div v-show="!isLoggingViewShow" style="width: 100%">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['project:scene:add']"
icon="el-icon-plus"
plain
size="mini"
type="primary"
@click="handleAdd"
>新增</el-button
>
<el-button size="mini" @click="handleQuery">刷新</el-button>
</el-col>
</el-row>
<div class="e-alarm-table">
<el-table
v-loading="tableLoading"
:data="tableList"
:height="total > 0 ? '470px' : '510px'"
>
<el-table-column
:index="indexFormatter"
align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
align="left"
label="场景名称"
prop="sceneName"
width="200px"
>
<template slot-scope="scope">
<span :title="scope.row.sceneName" class="lay-table-textarea">
{{ scope.row.sceneName }}
</span>
</template>
</el-table-column>
<el-table-column
align="left"
label="场景编码"
prop="sceneCode"
width="200"
>
<template slot-scope="scope">
<span :title="scope.row.sceneCode" class="lay-table-textarea">
{{ scope.row.sceneCode }}
</span>
</template>
</el-table-column>
<el-table-column
align="left"
label="场景模式"
prop="relation"
width="120"
>
<template slot-scope="scope">
<span :title="scope.row.relation" class="lay-table-textarea">
{{ scope.row.relation }}
</span>
</template>
</el-table-column>
<el-table-column align="center" label="状态" prop="runStatus">
<template slot-scope="scope">
<span class="lay-table-textarea">
{{ scope.row.runStatus == "0" ? "启用" : "停止" }}
</span>
</template>
</el-table-column>
<el-table-column
align="center"
label="创建时间"
prop="createTime"
width="160px"
>
<template slot-scope="scope">
<span :title="scope.row.createTime" class="lay-table-textarea">
{{ scope.row.createTime }}
</span>
</template>
</el-table-column>
<el-table-column
align="center"
label="操作"
prop="alarmTime"
width="300"
>
<template slot-scope="scope">
<el-button
v-hasPermi="['project:scene:edit']"
icon="el-icon-edit"
size="mini"
type="text"
@click="handleUpdate(scope.row)"
>编辑</el-button
>
<el-button
v-hasPermi="['project:scene:remove']"
icon="el-icon-delete"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>删除</el-button
>
<el-button
v-hasPermi="['project:scene:status']"
:icon="
scope.row.runStatus == '0'
? 'el-icon-open'
: 'el-icon-turn-off'
"
size="mini"
type="text"
@click="handleChangeStatus(scope.row)"
>{{ scope.row.runStatus == "0" ? "停止" : "启用" }}</el-button
>
<el-button
v-hasPermi="['project:scene:run']"
icon="el-icon-video-play"
size="mini"
type="text"
@click="handleSingleRun(scope.row)"
>执行</el-button
>
<el-button
icon="el-icon-takeaway-box"
size="mini"
type="text"
@click="handleLoggingView(scope.row)"
>指令历史</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:limit.sync="page.pageSize"
:page.sync="page.pageNum"
:total="total"
@pagination="getTableList"
/>
</div>
<div class="e-dialog">
<!-- 添加或修改建筑类型对话框 -->
<dialog-template
:title="title"
:visible="open"
width="880px"
@close="open = false"
>
<el-form
ref="form"
slot="dialog-center"
:model="form"
:rules="rules"
label-width="100px"
style="padding-right: 20px"
>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="场景名称:" prop="sceneName">
<el-input
v-model="form.sceneName"
placeholder="请输入场景名称"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="场景编码:" prop="sceneCode">
<el-input
v-model="form.sceneCode"
placeholder="请输入场景编码"
/>
</el-form-item>
</el-col>
<!-- <el-col :span="24">
<el-form-item label="描述" prop="buildingTypeName">
<el-input
v-model="form.buildingTypeName"
placeholder="请输入类型名称"
/>
</el-form-item>
</el-col> -->
<el-col :span="24">
<span
class="e-form-item__label"
style="
text-align: right;
vertical-align: middle;
font-size: 14px;
color: #606266;
width: 80px;
word-break: break-all;
font-weight: 600;
"
>
触发器列表:
</span>
<div>
<e-tag-card
v-for="(item, idx) in form.triggers"
:key="item.guid "
style="margin-top: 5px"
type="info"
>
<e-scene-triggers
slot="body"
:dataItem="item"
:sourceId="sourceId"
@change="
(v) => {
form.triggers[idx] = v;
}
"
@handleDel="
(v) => {
form.triggers.splice(idx, 1);
}
"
></e-scene-triggers>
</e-tag-card>
</div>
<el-button
icon="el-icon-plus"
type="text"
@click="handleAddTrigger"
>新增触发器</el-button
>
</el-col>
<el-col :span="24">
<div>
<span
class="e-form-item__label"
style="
text-align: right;
vertical-align: middle;
font-size: 14px;
color: #606266;
width: 80px;
word-break: break-all;
font-weight: 600;
"
>执行动作</span
>
</div>
<div>
<e-tag-card
v-for="(item, idx) in form.actions"
:key="item.guid "
style="margin-top: 5px"
type="info"
>
<e-scene-action
slot="body"
:dataItem="item"
:sourceId="sourceId"
@change="
(v) => {
form.actions[idx] = v;
}
"
@handleDel="
(v) => {
form.actions.splice(idx, 1);
}
"
/>
</e-tag-card>
</div>
<el-button
icon="el-icon-plus"
type="text"
@click="handleAddAction"
>新增动作</el-button
>
</el-col>
</el-row>
</el-form>
<div slot="dialog-footer" class="dialog-footer">
<el-button size="mini" type="primary" @click="submitForm"
>确 定</el-button
>
<el-button size="mini" @click="cancel">取 消</el-button>
</div>
</dialog-template>
</div>
</div>
<e-logging
v-if="isLoggingViewShow"
:sceneInfo="loggingSourceObject"
:sourceId="loggingSourceId"
@handleLinkToHome="
() => {
isLoggingViewShow = false;
}
"
></e-logging>
</div>
</template>
<script>
import {
projectSceneList,
projectSceneAdd,
projectSceneUpdate,
projectSceneDetail,
projectSceneDelete,
projectSceneChangeStatus,
projectSceneSingleRun,
} from "@/api/iot/project_new";
import DialogTemplate from "@/components/DialogTemplate";
import ESceneTriggers from "./ESceneTriggers/index";
import ETagCard from "@/components/Cards/ETagCard";
import ESceneAction from "./ESceneAction/index";
import ELogging from "./ELogging";
export default {
name: "ESceneManage",
props: {
projectInfo: {
type: Object,
require: true,
},
sourceId: {
type: [Number, String],
require: true,
},
tempType: {
type: String,
require: true,
},
isFoldRight: {
type: Boolean,
default: () => {
return false;
},
},
isShrink: {
type: Boolean,
default: () => {
return false;
},
},
},
components: {
DialogTemplate,
ESceneTriggers,
ETagCard,
ESceneAction,
ELogging,
},
data() {
return {
queryParams: {},
isLoggingViewShow: false,
loggingSourceId: null,
loggingSourceObject: {},
page: {
pageNum: 1,
pageSize: 10,
orderByColumn: "createTime",
isAsc: "desc",
},
title: "新增场景",
total: 0,
tableList: [],
tableLoading: false,
open: false,
// 表单参数
form: {},
// 表单校验
rules: {
sceneName: [
{ required: true, message: "场景名称不能为空", trigger: "change" },
],
sceneCode: [
{
required: true,
validator: this.chenking_sceneCode,
trigger: "change",
},
],
},
};
},
watch: {
isFoldRight() {
this.$forceUpdate();
},
isShrink() {
this.$forceUpdate();
},
sourceId(val) {
if (val !== null && val !== undefined) {
this.handleQuery();
}
},
tempType(val) {
if (val) {
this.init();
}
},
},
mounted() {},
created() {
this.init();
},
methods: {
chenking_sceneCode(rule, value, callback) {
const isExp = /^[A-Z a-z 0-9 _ - $]{0,36}$/;
if (!this.form.sceneCode || this.form.sceneCode.length <= 0) {
callback(new Error("场景编码不能为空!"));
} else if (this.form.sceneCode && !isExp.test(this.form.sceneCode)) {
callback(new Error("格式不正确(数字英文字母大小写36个字符)"));
} else {
callback();
}
},
handleAddAction() {
let obj = {
guid: this.getGuid(),
orderBy: this.form.actions.length + 1 || 1,
recordStatus: 0,
actionId: null,
sceneId: this.form.recordId || null,
actionType: "DEVOUTPUT",
actionAttr: null,
sceneActionDevices: [],
sceneActionNotifierContacts: [],
};
this.form.actions.push(obj);
},
// 获取标记
handleAddTrigger() {
let triggersPop = [...this.form.triggers].pop();
let obj = {
guid: this.getGuid(),
orderBy: triggersPop ? triggersPop.orderBy + 1 : 1,
method: "",
conditions: [],
intervalVal: "60",
intervalUnit: "SECONDS",
sceneTriggerDevices: [],
execScript: "",
};
this.form.triggers.push(obj);
},
// 验证 触发器 条件
validateTrigger() {
if (!this.form.triggers || this.form.triggers.length <= 0) {
this.msgError("至少有一条触发器!");
return false;
}
var isTrue = true;
this.form.triggers.forEach((e) => {
if (!e.method) {
this.msgError("设备触发__至少选择一种类型");
isTrue = false;
}
if (
e.method === "DEVICE" &&
(!e.conditions || e.conditions.length <= 0)
) {
this.msgError("设备触发__至少选择一条设备以及触发条件");
isTrue = false;
}
});
return isTrue && this.validateAction();
},
// 验证 执行条件
validateAction() {
if (!this.form.actions || this.form.actions.length <= 0) {
this.msgError("至少有一执行条件!");
return false;
}
var isTrue = true;
this.form.actions.forEach((e) => {
if (
e.actionType === "DEVOUTPUT" &&
e.sceneActionDevices[0] &&
(!e.sceneActionDevices[0]["cmdKey"] ||
!e.sceneActionDevices[0]["deviceKey"])
) {
this.msgError("执行条件中有条件未选择设备或者分组!");
isTrue = false;
}
if (e.actionType === "NOTIFIER") {
let arr = e.sceneActionNotifierContacts.filter((v) => {
if ((!v["contactsRelList"]) || v["contactsRelList"].length <= 0) {
return v;
}
});
if (arr && arr.length > 0) {
this.msgError("执行条件中有条件未选择联系人!");
isTrue = false;
}
}
});
return isTrue;
},
submitForm() {
console.log("submit---", this.form);
this.$refs["form"].validate((valid) => {
if (valid && this.validateTrigger()) {
if (this.form.recordId != null) {
projectSceneUpdate(
Object.assign(this.form, {
projectId: this.sourceId,
})
).then((response) => {
this.msgSuccess("修改成功");
this.open = false;
this.handleQuery();
});
} else {
projectSceneAdd(
Object.assign(this.form, {
projectId: this.sourceId,
})
).then((response) => {
this.msgSuccess("新增成功");
this.open = false;
this.handleQuery();
});
}
}
});
},
indexFormatter(val) {
return val + 1 + (this.page.pageNum - 1) * this.page.pageSize;
},
handleAdd() {
this.reset();
this.title = "新增场景";
this.open = true;
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
projectSceneDetail(row.recordId).then((response) => {
this.form = response.data;
this.open = true;
this.title = "编辑场景";
});
},
handleChangeStatus(row) {
this.$confirm(
row.runStatus == "0" ? "是否停止场景?" : "是否开启场景?",
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(function () {
return projectSceneChangeStatus({
recordId: row.recordId,
runStatus: row.runStatus == "0" ? "1" : "0",
});
})
.then(() => {
this.handleQuery();
this.msgSuccess("成功");
});
},
handleLoggingView(row) {
this.loggingSourceId = row.recordId;
this.loggingSourceObject = row;
this.isLoggingViewShow = true;
},
/**
* 场景 执行一次 方法
* @param {*} row
*/
handleSingleRun(row) {
this.$confirm("是否确认执行一次此场景?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return projectSceneSingleRun(row.recordId);
})
.then(() => {
this.handleQuery();
this.msgSuccess("请求成功!");
});
},
handleDelete(row) {
const projectIds = row.recordId;
this.$confirm("是否删除该选项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return projectSceneDelete(projectIds);
})
.then(() => {
this.handleQuery();
this.msgSuccess("删除成功");
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
recordId: null,
recordStatus: 0,
buildingTypeCode: null,
buildingTypeName: null,
triggers: [],
actions: [],
};
this.resetForm("form");
},
init() {
this.handleQuery();
},
handleQuery() {
this.page.pageNum = 1;
this.getTableList();
},
// 查询 表格 数据
getTableList() {
this.tableLoading = true;
let query = JSON.parse(JSON.stringify(this.queryParams));
projectSceneList(
Object.assign(
query,
{
projectId: this.sourceId,
},
this.page
)
).then((res) => {
this.tableList = res.rows;
this.tableLoading = false;
this.total = res.total;
});
},
},
};
</script>
<style lang="scss">
.e-scene-manage {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
.e-alarm-heard {
width: 100%;
height: 40px;
display: flex;
justify-content: flex-end;
align-items: center;
.heard-query {
width: 50%;
height: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
width: calc(100% - 300px);
.data-type {
width: 32px;
height: 32px;
background: #f4f5f7;
border-radius: 50%;
font-size: 14px;
font-family: Source Han Sans CN;
font-weight: 300;
color: #6b778c;
display: flex;
justify-content: center;
align-items: center;
margin: 0 5px;
cursor: default;
}
.data-type-selected {
background: #1890ff;
color: #f4f5f7;
}
.other-query {
display: flex;
width: 420px;
justify-content: space-evenly;
align-items: center;
}
.other-print {
font-size: 20px;
}
.other-print:hover {
color: #1890ff;
}
}
}
.e-alarm-echarts {
width: 100%;
height: 300px;
}
.e-alarm-table {
width: 100%;
padding-top: 10px;
}
.pagination-container {
margin-top: 5px;
height: 35px;
}
.e-form-item__label {
text-align: right;
vertical-align: middle;
font-size: 14px;
color: #606266;
width: 80px;
word-break: break-all;
font-weight: 600;
}
}
</style>