开源版新增规则脚本

This commit is contained in:
kerwincui
2024-04-23 16:34:20 +08:00
parent de7e2529a3
commit 054e414b48
50 changed files with 7233 additions and 13 deletions

View File

@@ -0,0 +1,103 @@
<template>
<div style="border: 0px solid #ebebeb; overflow: hidden; border-radius: 6px; background-color: #ebebeb; padding: 8px 5px 8px 0">
<editor ref="codeEditor" v-model="currentContent" @init="editorInit" :options="options" :lang="lang" :theme="codeStyle" :width="width" :height="height" />
</div>
</template>
<script>
// import { mapState } from 'vuex';
export default {
name: 'AceEditor',
components: {
editor: require('vue2-ace-editor'),
},
props: {
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: '500px',
},
content: {
type: String,
required: true,
default: () => null,
},
lang: {
type: String,
default: 'groovy',
},
readOnly: {
type: Boolean,
default: false,
},
codeStyle: {
type: String,
default: 'chrome',
},
},
data() {
return {
options: {
autoScrollEditorIntoView: true,
// enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
// 只读
readOnly: this.readOnly,
// 显示打印边距线
showPrintMargin: false,
// 字体大小
fontSize: 13,
},
};
},
computed: {
// ...mapState({
// codeStyle: (state) => state.settings.codeStyle,
// codeSize: (state) => state.settings.codeSize,
// }),
currentContent: {
get() {
return this.content;
},
set(val) {
this.$emit('update:content', val);
},
},
},
watch: {
codeSize: {
handler: function (value) {
this.$refs.codeEditor.editor.setOptions({
fontSize: value,
});
},
deep: true,
},
},
created() {},
mounted() {},
methods: {
editorInit(editor) {
require('brace/ext/language_tools');
require('brace/mode/groovy');
require('brace/mode/mysql');
require('brace/mode/json');
require('brace/theme/chrome');
require('brace/snippets/groovy');
require('brace/snippets/json');
require('brace/ext/beautify');
},
format() {
const ace = require('brace');
const editor = this.$refs.codeEditor.editor;
const beautify = ace.acequire('ace/ext/beautify');
beautify.beautify(editor.session);
},
},
};
</script>

View File

@@ -0,0 +1,180 @@
<template>
<el-dialog title="选择设备" :visible.sync="openDeviceList" width="900px" append-to-body>
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="设备编号" prop="serialNumber">
<el-input v-model="queryParams.serialNumber" placeholder="请输入设备编号" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table ref="multipleTable" v-loading="loading" :data="deviceList" @select="handleSelectionChange" row-key="serialNumber" size="mini">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备编号" align="center" prop="serialNumber" />
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="设备类型" align="center" width="75">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.isOwner == 0">分享</el-tag>
<el-tag type="primary" v-else>拥有</el-tag>
</template>
</el-table-column>
<el-table-column label="定位方式" align="center" prop="locationWay" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.iot_location_way" :value="scope.row.locationWay" />
</template>
</el-table-column>
<el-table-column label="设备状态" align="center" prop="status" width="80">
<template slot-scope="scope">
<dict-tag :options="dict.type.iot_device_status" :value="scope.row.status" />
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList(null)" />
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="confirmSelectDevice"> </el-button>
<el-button @click="closeSelectDeviceList"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listDeviceShort } from '@/api/iot/device';
export default {
name: 'device-list',
dicts: ['iot_device_status', 'iot_location_way'],
data() {
return {
// 遮罩层
loading: true,
// 选中设备
selectDeviceNums: [],
productId: 0,
productName: '',
// 是否显示设备列表
openDeviceList: false,
// 总条数
total: 0,
// 设备表格数据
deviceList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
deviceName: null,
productId: null,
productName: null,
serialNumber: null,
status: null,
},
};
},
created() {},
methods: {
// 获取设备列表
getList() {
this.deviceList = [];
this.loading = true;
this.queryParams.productId = this.queryParams.productId == 0 ? null : this.queryParams.productId;
listDeviceShort(this.queryParams).then((response) => {
this.deviceList = response.rows;
this.total = response.total;
this.loading = false;
// 设置选中
if (this.selectDeviceNums) {
this.deviceList.forEach((row) => {
this.$nextTick(() => {
if (this.selectDeviceNums.some((x) => x === row.serialNumber)) {
this.$refs.multipleTable.toggleRowSelection(row, true);
}
});
});
} else {
// 初始化
this.selectDeviceNums = [];
}
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList(null);
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm');
this.handleQuery();
},
/** 多选框选中数据 */
handleSelectionChange(selection, row) {
// 设备ID是否存在于原始设备ID数组中
let index = this.selectDeviceNums.indexOf(row.serialNumber);
// 是否选中
let value = selection.indexOf(row);
if (index == -1 && value != -1) {
// 不存在且选中
this.selectDeviceNums.push(row.serialNumber);
this.productId = row.productId;
this.productName = row.productName;
} else if (index != -1 && value == -1) {
// 存在且取消选中
this.selectDeviceNums.splice(index, 1);
}
// 筛选产品下的设备比
if (this.selectDeviceNums.length == 0) {
this.queryParams.productId = null;
this.getList();
} else if (this.selectDeviceNums.length == 1) {
this.queryParams.productId = row.productId;
this.getList();
}
},
// 全选事件处理
handleSelectionAll(selection) {
for (let i = 0; i < this.deviceList.length; i++) {
// 设备ID是否存在于原始设备ID数组中
let index = this.selectDeviceNums.indexOf(this.deviceList[i].serialNumber);
// 是否选中
let value = selection.indexOf(this.deviceList[i]);
if (index == -1 && value != -1) {
// 不存在且选中
this.selectDeviceNums.push(this.deviceList[i].serialNumber);
} else if (index != -1 && value == -1) {
// 存在且取消选中
this.selectDeviceNums.splice(index, 1);
}
}
},
// 关闭选择设备列表
closeSelectDeviceList() {
this.openDeviceList = false;
},
/**确定选择设备,设备传递给父组件 */
confirmSelectDevice() {
if (this.selectDeviceNums.length > 0) {
var data = {
productId: this.productId,
productName: this.productName,
deviceNums: this.selectDeviceNums,
};
this.$emit('deviceEvent', data);
}
this.openDeviceList = false;
},
},
};
</script>
<style lang="scss" scoped>
/***隐藏全选,避免选中不同产品的设备**/
::v-deep .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,253 @@
<template>
<div style="padding: 6px">
<el-card v-show="showSearch" style="margin-bottom: 6px">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px" style="margin-bottom: -20px">
<el-form-item label="告警名称" prop="alertName">
<el-input v-model="queryParams.alertName" placeholder="请输入告警名称" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="告警级别" prop="alertLevel">
<el-select v-model="queryParams.alertLevel" placeholder="请选择告警级别" clearable size="small">
<el-option v-for="dict in dict.type.iot_alert_level" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="处理状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择处理状态" clearable size="small">
<el-option v-for="dict in dict.type.iot_process_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="padding-bottom: 100px">
<el-table v-loading="loading" :data="alertLogList" @selection-change="handleSelectionChange" border>
<el-table-column label="告警名称" align="center" prop="alertName" />
<el-table-column label="设备编号" align="center" prop="serialNumber" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="告警级别" align="center" prop="alertLevel" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.iot_alert_level" :value="scope.row.alertLevel" />
</template>
</el-table-column>
<el-table-column label="告警时间" align="center" prop="createTime" width="170">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="数据" align="left" header-align="center" prop="detail">
<template slot-scope="scope">
<div v-html="formatDetail(scope.row.detail)"></div>
</template>
</el-table-column>
<el-table-column label="处理状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.iot_process_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['iot:alertLog:edit']">处理</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改设备告警对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="处理结果" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" rows="8" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</el-card>
</div>
</template>
<script>
// import { listAlertLog, getAlertLog, delAlertLog, addAlertLog, updateAlertLog } from '@/api/iot/alertLog';
export default {
name: 'SceneLog',
dicts: ['iot_alert_level', 'iot_process_status'],
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 设备告警表格数据
alertLogList: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
alertName: null,
alertLevel: null,
status: null,
productId: null,
productName: null,
deviceId: null,
deviceName: null,
},
// 表单参数
form: {},
// 表单校验
rules: {
remark: [
{
required: true,
message: '处理内容不能为空',
trigger: 'blur',
},
],
},
};
},
created() {
this.getList();
},
methods: {
/** 查询设备告警列表 */
getList() {
this.loading = true;
listAlertLog(this.queryParams).then((response) => {
this.alertLogList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
alertLogId: null,
alertName: null,
alertLevel: null,
status: null,
productId: null,
productName: null,
deviceId: null,
deviceName: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
remark: null,
};
this.resetForm('form');
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm');
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.alertLogId);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = '添加设备告警';
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const alertLogId = row.alertLogId || this.ids;
getAlertLog(alertLogId).then((response) => {
this.form = response.data;
this.open = true;
this.title = '修改设备告警';
});
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.alertLogId != null) {
updateAlertLog(this.form).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
});
} else {
addAlertLog(this.form).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const alertLogIds = row.alertLogId || this.ids;
this.$modal
.confirm('是否确认删除设备告警编号为"' + alertLogIds + '"的数据项?')
.then(function () {
return delAlertLog(alertLogIds);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download(
'iot/alertLog/export',
{
...this.queryParams,
},
`alertLog_${new Date().getTime()}.xlsx`
);
},
/**格式化显示物模型**/
formatDetail(json) {
if (json == null || json == '') {
return;
}
let item = JSON.parse(json);
let result = 'id<span style="color:#F56C6C">' + item.id + '</span><br />';
result = result + 'value<span style="color:#F56C6C">' + item.value + '</span><br />';
result = result + 'remark<span style="color:#F56C6C">' + item.remark + '</span>';
return result;
},
},
};
</script>

View File

@@ -0,0 +1,147 @@
<template>
<el-dialog title="选择产品" :visible.sync="open" width="800px">
<div style="margin-top: -55px">
<el-divider style="margin-top: -30px"></el-divider>
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
<el-form-item label="产品名称" prop="productName">
<el-input v-model="queryParams.productName" placeholder="请输入产品名称" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" ref="singleTable" :data="productList" @row-click="rowClick" highlight-current-row size="mini">
<el-table-column label="选择" width="50" align="center">
<template slot-scope="scope">
<input type="radio" :checked="scope.row.isSelect" name="product" />
</template>
</el-table-column>
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="分类名称" align="center" prop="categoryName" />
<el-table-column label="租户名称" align="center" prop="tenantName" />
<el-table-column label="授权码" align="center" prop="status" width="70">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.isAuthorize == 1">启用</el-tag>
<el-tag type="info" v-if="scope.row.isAuthorize == 0">未启用</el-tag>
</template>
</el-table-column>
<el-table-column label="认证方式" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.iot_vertificate_method" :value="scope.row.vertificateMethod" />
</template>
</el-table-column>
<el-table-column label="联网方式" align="center" prop="networkMethod">
<template slot-scope="scope">
<dict-tag :options="dict.type.iot_network_method" :value="scope.row.networkMethod" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="100">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="confirmSelectProduct" type="primary">确定</el-button>
<el-button @click="closeDialog" type="info"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listProduct } from '@/api/iot/product';
export default {
name: 'ProductList',
dicts: ['iot_vertificate_method', 'iot_network_method'],
data() {
return {
// 遮罩层
loading: true,
// 总条数
total: 0,
// 打开选择产品对话框
open: false,
// 产品列表
productList: [],
// 选中的产品编号
selectProductId: 0,
// 选中的产品
product: {},
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
productName: null,
categoryId: null,
categoryName: null,
tenantId: null,
tenantName: null,
isSys: null,
status: 2, //已发布
deviceType: null,
networkMethod: null,
},
};
},
created() {},
methods: {
/** 查询产品列表 */
getList() {
this.loading = true;
listProduct(this.queryParams).then((response) => {
//产品列表初始化isSelect值用于单选
for (let i = 0; i < response.rows.length; i++) {
response.rows[i].isSelect = false;
}
this.productList = response.rows;
this.total = response.total;
this.loading = false;
// 设置产品选中
this.setRadioSelected(this.selectProductId);
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm');
this.handleQuery();
},
/** 单选数据 */
rowClick(product) {
if (product != null) {
this.setRadioSelected(product.productId);
this.product = product;
}
},
/** 设置单选按钮选中 */
setRadioSelected(productId) {
for (let i = 0; i < this.productList.length; i++) {
if (this.productList[i].productId == productId) {
this.productList[i].isSelect = true;
} else {
this.productList[i].isSelect = false;
}
}
},
/**确定选择产品,产品传递给父组件 */
confirmSelectProduct() {
this.$emit('productEvent', this.product);
this.open = false;
},
/**关闭对话框 */
closeDialog() {
this.open = false;
},
},
};
</script>

View File

@@ -0,0 +1,384 @@
<template>
<div style="padding: 6px">
<el-card v-show="showSearch" style="margin-bottom: 6px">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
label-width="68px" style="margin-bottom: -20px">
<el-form-item label="脚本标识" prop="scriptId">
<el-input v-model="queryParams.scriptId" placeholder="请输入脚本名" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="脚本名" prop="scriptName">
<el-input v-model="queryParams.scriptName" placeholder="请输入脚本名" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<el-form-item style="float: right">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['iot:script:add']">新增</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="padding-bottom: 100px">
<el-table v-loading="loading" :data="scriptList" @selection-change="handleSelectionChange">
<el-table-column label="脚本名称" align="center" prop="scriptName" />
<el-table-column label="所属产品" align="center" prop="productName" />
<el-table-column label="脚本标识" align="center" prop="scriptId" width="180" />
<el-table-column label="脚本事件" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.rule_script_event" :value="scope.row.scriptEvent" size="small" />
</template>
</el-table-column>
<el-table-column label="脚本动作" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.rule_script_action" :value="scope.row.scriptAction"
size="small" />
</template>
</el-table-column>
<el-table-column label="脚本语言" align="center" prop="scriptLanguage" />
<el-table-column label="状态" align="center" prop="enable" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.enable == 1" type="success" size="small">启动</el-tag>
<el-tag v-if="scope.row.enable == 0" type="danger" size="small">暂停</el-tag>
</template>
</el-table-column>
<el-table-column label="执行顺序" align="center" prop="scriptOrder" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleUpdate(scope.row)"
v-hasPermi="['iot:script:query']">查看</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['iot:script:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改规则引擎脚本对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false"
:close-on-press-escape="false">
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-row :gutter="50">
<el-col :span="12">
<el-form-item label="脚本名称" prop="scriptName">
<el-input v-model="form.scriptName" placeholder="请输入脚本名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="执行顺序" prop="scriptOrder">
<el-input-number v-model="form.scriptOrder" placeholder="请输入脚本名" type="number"
controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="脚本事件" prop="scriptEvent">
<el-select v-model="form.scriptEvent" placeholder="请选择脚本事件" style="width: 100%">
<el-option v-for="dict in dict.type.rule_script_event" :key="dict.label"
:label="dict.label" :value="Number(dict.value)"
:disabled="dict.value !== '1' && dict.value !== '2'"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="脚本动作" prop="scriptAction">
<el-select v-model="form.scriptAction" placeholder="请选择脚本动作" style="width: 100%">
<el-option v-for="dict in dict.type.rule_script_action" :key="dict.label"
:label="dict.label" :value="Number(dict.value)"
:disabled="dict.value !== '1'"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="脚本状态" prop="enable">
<el-switch v-model="form.enable" :active-value="1" :inactive-value="0" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属产品" prop="productName">
<el-input readonly v-model="form.productName" size="small" placeholder="请选择产品"
style="margin-top: 3px">
<el-button slot="append" @click="handleSelectProduct()"
size="small">选择产品</el-button>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12" style="float: right"></el-col>
</el-row>
</el-form>
<div style="padding: 0px 10px" @click="editClick">
<AceEditor ref="codeEditor" :content.sync="form.scriptData" lang="groovy" codeStyle="chrome"
:read-only="false" width="100%" height="450px"></AceEditor>
</div>
<div style="padding: 0 10px; margin: 10px 0">
<el-alert :title="validateMsg" type="success" show-icon v-if="isValidate && validateMsg"
:closable="false"></el-alert>
<el-alert :title="validateMsg" type="error" show-icon v-if="!isValidate && validateMsg"
:closable="false"></el-alert>
</div>
<div slot="footer" class="dialog-footer">
<span style="float: left">
<el-link style="line-height: 40px; padding-left: 20px" icon="el-icon-question"
:underline="false" type="primary" href="https://fastbee.cn/doc/pages/rule_engine/"
target="_blank">
脚本使用Groovy引擎查看教程>>>
</el-link>
</span>
<el-button type="success" @click="handleValidate"> </el-button>
<el-button type="primary" @click="submitForm" v-hasPermi="['iot:script:edit']"
v-show="form.scriptId" :disabled="!isValidate">
</el-button>
<el-button type="primary" @click="submitForm" v-hasPermi="['iot:script:add']"
v-show="!form.scriptId" :disabled="!isValidate">
</el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</el-card>
<!-- 产品列表 -->
<productList ref="productList" @productEvent="getSelectProduct($event)"></productList>
</div>
</template>
<script>
import { listScript, getScript, delScript, addScript, updateScript, validateScript } from '@/api/iot/script';
import AceEditor from '@/views/components/editor/editor.vue';
import productList from './product-list';
export default {
name: 'Script',
dicts: ['rule_script_type', 'rule_script_language', 'rule_script_event', 'rule_script_action'],
components: {
AceEditor,
productList,
},
data() {
// 自定义验证规则
var checkScriptId = (rule, value, callback) => {
const regex = /^[a-zA-Z]+[0-9]*[a-zA-Z]*$/; // 定义只包含字母和数字,且字母开头的正则表达式
if (!regex.test(value)) {
return callback(new Error('脚本标识只能输入字母和数字,且字母开头'));
} else {
callback();
}
};
return {
// 脚本数据验证
isValidate: false,
// 脚本数据验证结果
validateMsg: '',
// 遮罩层
loading: true,
// 选中数组
scriptIds: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 规则引擎脚本表格数据
scriptList: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
scriptPurpose: 1, // 只展示数据流(1=数据流2=触发器3=执行动作)
scriptId: null,
scriptName: null,
scriptData: null,
scriptType: null,
scriptLanguage: null,
enable: null,
},
// 表单参数
form: {},
// 表单校验
rules: {
scriptId: [{ required: true, message: '脚本标识不能为空', trigger: 'blur' }],
productName: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
scriptName: [{ required: true, message: '脚本名不能为空', trigger: 'blur' }],
scriptType: [{ required: true, message: '脚本类型不能为空', trigger: 'change' }],
scriptLanguage: [{ required: true, message: '脚本语言不能为空', trigger: 'change' }],
scriptEvent: [{ required: true, message: '', trigger: 'change' }],
scriptAction: [{ required: true, message: '', trigger: 'change' }],
scriptOrder: [{ required: true, message: '', trigger: 'change' }],
enable: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
},
};
},
created() {
this.getList();
},
methods: {
/** 查询规则引擎脚本列表 */
getList() {
this.loading = true;
listScript(this.queryParams).then((response) => {
this.scriptList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.validateMsg = '';
this.isValidate = false;
this.form = {
id: null,
applicationName: 'fastbee', // 后端配置和规则/脚本需要一致
scriptId: null,
productId: null,
productName: '',
scriptName: null,
scriptType: 'script',
remark: null,
scriptLanguage: 'groovy',
enable: 1,
scriptPurpose: 1, // 脚本用途(1=数据流2=触发器3=执行动作)
scriptOrder: 1, // 脚本执行顺序,数字越大越先执行
scriptAction: 1, // 脚本动作(1=消息重发2=消息通知3=Http推送4=Mqtt桥接5=数据库存储)
scriptEvent: 1, // 脚本事件(1=设备上报2=平台下发3=设备上线4=设备离线)
sceneId: 0,
scriptData: `import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.util.NumberUtil;
// 1. 获取主题和内容(必要)
String topic = msgContext.getTopic();
String payload = msgContext.getPayload();
// 2. 数据转换(自己处理)
println ("根据情况转换数据")
String NewTopic = topic;
String NewPayload = payload;
// 3. 返回新的数据(必要)
msgContext.setTopic(NewTopic);
msgContext.setPayload(NewPayload);`,
};
this.resetForm('form');
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm');
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.scriptIds = selection.map((item) => item.scriptId);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = '编辑规则脚本';
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const scriptId = row.scriptId || this.scriptIds;
getScript(scriptId).then((response) => {
this.form = response.data;
this.open = true;
this.title = '修改规则引擎脚本';
});
},
/**选择产品 */
handleSelectProduct(data) {
// 刷新子组建
this.$refs.productList.queryParams.pageNum = 1;
this.$refs.productList.open = true;
this.$refs.productList.selectProductId = this.form.productId;
this.$refs.productList.getList();
},
getSelectProduct(data) {
this.form.productId = data.productId;
this.form.productName = data.productName;
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.scriptId != null) {
updateScript(this.form).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
});
} else {
addScript(this.form).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const scriptIds = row.scriptId || this.scriptIds;
this.$modal
.confirm('是否确认删除规则引擎脚本编号为"' + scriptIds + '"的数据项?')
.then(function () {
return delScript(scriptIds);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => { });
},
/** 验证按钮操作 */
handleValidate() {
this.validateMsg = '';
this.isValidate = false;
validateScript(this.form).then((response) => {
this.isValidate = response.data;
this.validateMsg = response.msg;
});
},
/** 编辑器单机事件 */
editClick() {
this.validateMsg = '';
this.isValidate = false;
},
/** 导出按钮操作 */
handleExport() {
this.download(
'iot/script/export',
{
...this.queryParams,
},
`script_${new Date().getTime()}.xlsx`
);
},
},
};
</script>