Commit 3d8dc5f6 by 吴斌

update:完成规则脚本对Lua的支持。

parent 4d6bcd58
......@@ -1173,6 +1173,30 @@
"reusify": "^1.0.4"
}
},
"fengari": {
"version": "0.1.4",
"resolved": "https://registry.npmmirror.com/fengari/-/fengari-0.1.4.tgz",
"integrity": "sha512-6ujqUuiIYmcgkGz8MGAdERU57EIluGGPSUgGPTsco657EHa+srq0S3/YUl/r9kx1+D+d4rGfYObd+m8K22gB1g==",
"requires": {
"readline-sync": "^1.4.9",
"sprintf-js": "^1.1.1",
"tmp": "^0.0.33"
}
},
"fengari-interop": {
"version": "0.1.3",
"resolved": "https://registry.npmmirror.com/fengari-interop/-/fengari-interop-0.1.3.tgz",
"integrity": "sha512-EtZ+oTu3kEwVJnoymFPBVLIbQcCoy9uWCVnMA6h3M/RqHkUBsLYp29+RRHf9rKr6GwjubWREU1O7RretFIXjHw=="
},
"fengari-web": {
"version": "0.1.4",
"resolved": "https://registry.npmmirror.com/fengari-web/-/fengari-web-0.1.4.tgz",
"integrity": "sha512-f+W/Csx9VNyKttxYjZnk6290+Pcs7w7noDVhkuPEt0e51GWoD32vSNHFXhZYzTe8Ni/bhbk5VocNV1RBIgO5iA==",
"requires": {
"fengari": "^0.1.4",
"fengari-interop": "^0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz",
......@@ -1647,6 +1671,11 @@
"mimic-fn": "^2.1.0"
}
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
},
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
......@@ -1824,6 +1853,11 @@
"picomatch": "^2.2.1"
}
},
"readline-sync": {
"version": "1.4.10",
"resolved": "https://registry.npmmirror.com/readline-sync/-/readline-sync-1.4.10.tgz",
"integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw=="
},
"regenerator-runtime": {
"version": "0.14.0",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
......@@ -1915,6 +1949,11 @@
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
},
"sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
},
"strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
......@@ -1995,6 +2034,14 @@
"resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"requires": {
"os-tmpdir": "~1.0.2"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
......
......@@ -12,6 +12,8 @@
"@element-plus/icons-vue": "^2.1.0",
"@types/node": "^20.6.0",
"element-plus": "^2.3.12",
"fengari": "^0.1.4",
"fengari-web": "^0.1.4",
"gojs": "^2.1.48",
"mathjs": "^12.0.0",
"vue": "^3.3.4",
......
......@@ -203,6 +203,7 @@
<div>
<el-button type="primary" @click="addRuleParam">添加参数</el-button>
<div v-for="(input,index) in ruleDialog.data.inputs" class="flex mt-2 space-x-1">
<div class="font-bold mr-2">{{index}}</div>
<el-select v-model="input['key']" class="flex-1">
<el-option
v-for="device in deviceMap"
......@@ -269,7 +270,6 @@ import {
} from "./kit/core/Analyse.ts";
import {addRule, deleteRuleById, rules, runAllEnableRule, testRuleById, updateRule} from "./kit/rule/Rule";
import {diagramModelData} from "./kit/ModelData.ts";
import {convertSVGToGeometry} from "./kit/core/SVG2Geometry.ts";
// 变量定义
// region
// 图表配置
......@@ -341,6 +341,7 @@ const ruleDialog = ref<Record<string, any>>({
type:"add",
data:{
name: "",
description:"",
inputs:[],
func:"",
}
......@@ -538,7 +539,8 @@ function listenDiagram(){
});
myDiagram.addModelChangedListener(function(e:any){
if (e.isTransactionFinished) {
runAllEnableRule(getDiagramMapData(myDiagram))
deviceMap.value = getDiagramMapData(myDiagram)
runAllEnableRule(deviceMap.value)
}
})
}
......@@ -868,9 +870,9 @@ function confirmAddRule(){
return
}
if(ruleDialog.value.type === 'add'){
addRule(ruleData.name, ruleData.inputs, ruleData.func)
addRule(ruleData.name, ruleData.description, ruleData.inputs, ruleData.func)
}else if(ruleDialog.value.type === 'update'){
updateRule(ruleData.id, ruleData.name, ruleData.inputs, ruleData.func)
updateRule(ruleData.id, ruleData.name, ruleData.description, ruleData.inputs, ruleData.func)
}
ruleDialog.value.visible = false
......
......@@ -7787,6 +7787,45 @@ export const diagramModelData = {
]
},
ruleData:[
// {
// "id": "ffdb88cf1809049819226d3e617a1fbd4",
// "type": "js",
// "name": "1",
// "inputs": [
// {
// "key": -1,
// "valueKey": "name",
// "testData": ""
// },
// {
// "key": -2,
// "valueKey": "name",
// "testData": ""
// }
// ],
// "description": "1",
// "func": "return data[0]",
// "enable": false
// },
{
"id": "f3b59c21947034e6f81506812ccbaa2a8",
"type": "lua",
"name": "2",
"inputs": [
{
"key": -1,
"valueKey": "name",
"testData": ""
},
{
"key": -2,
"valueKey": "name",
"testData": ""
}
],
"description": "2",
"func": "return data[1]",
"enable": true
}
]
}
import {uuid} from "vue3-uuid";
import * as fengari from 'fengari-web';
export class RuleScriptType {
static Lua = 'lua'
static JS = 'js'
}
/**
* {
* id: string // 规则id 也是函数名
* type: string // 规则语法类型 例如:lua,js等 暂定为只有lua
* inputs:[
* key: 对应设备的唯一id,
* valueKey: "name", 指定设备下的属性key,
* testData: 测试数据
* ] 输入的参数列表
* func: string // 规则函数
* enable: boolean // 是否启用
* name: string // 规则名称
* description: string // 规则描述
* actions: [
* type: 通知的类型 例如:success,info,warning,error
* content: string, 通知的内容
* ] // 规则动作 根据用户填写的规则的返回值来确定触发的效果
* }
*/
export var rules: Record<string, any>[] = []
export var rules :Record<string, any>[]= []
/**
* 添加规则
* @param name 规则名称
* @param inputs 输入参数 [{key:-1 ,valueKey:'thick',testData:""}] key表示节点在diagram中的唯一id,valueKey表示节点的属性key
* @param description 规则描述
* @param inputs 输入参数
* @param func 规则函数
* @param actions 规则动作
*/
export function addRule(name:string, inputs:any[], func:Function){
export function addRule(name: string, description: string, inputs: any[], func: Function, actions:any[]=[]) {
const ruleId = 'f' + uuid.v4().split('-').join('')
rules.push({
id: uuid.v4(),
id: ruleId,
name: name,
inputs: inputs,
description: description,
func: func,
enable:false,
enable: false,
type: RuleScriptType.Lua, // 暂定为只有lua
actions: actions
})
}
......@@ -22,14 +54,16 @@ export function addRule(name:string, inputs:any[], func:Function){
* 更新规则
* @param id 规则id
* @param name 规则名称
* @param description 规则描述
* @param inputs 输入参数
* @param func 规则函数
*/
export function updateRule(id:string, name:string, inputs:[], func:Function){
let ruleIndex = rules.findIndex((item:any) => item.id == id)
if (ruleIndex !== -1){
export function updateRule(id: string, name: string, description: string, inputs: [], func: Function) {
let ruleIndex = rules.findIndex((item: any) => item.id == id)
if (ruleIndex !== -1) {
rules[ruleIndex].name = name
rules[ruleIndex].inputs = inputs
rules[ruleIndex].description = description
rules[ruleIndex].func = func
}
}
......@@ -38,8 +72,8 @@ export function updateRule(id:string, name:string, inputs:[], func:Function){
* 删除规则
* @param id
*/
export function deleteRuleById(id:string){
rules.splice(rules.findIndex((item:any) => item.id == id), 1)
export function deleteRuleById(id: string) {
rules.splice(rules.findIndex((item: any) => item.id == id), 1)
}
......@@ -48,20 +82,26 @@ export function deleteRuleById(id:string){
* @param rule 规则
* @param deviceMap 设备数据
*/
export function runRule(rule:any, deviceMap:Record<string, any>){
export function runRule(rule: any, deviceMap: Record<string, any>) {
let inputData = []
let runFunc = null
if (rule){
for (let input of rule.inputs){
let result = null
if (rule) {
for (let input of rule.inputs) {
inputData.push(deviceMap[input.key][input.valueKey])
}
runFunc = new Function( "return " + rule.func)
try {
runFunc()(...inputData)
}catch (e){
alert(e)
switch (rule['type']) {
case RuleScriptType.Lua:
result = runLua(rule, inputData)
break
case RuleScriptType.JS:
result = runJS(rule, inputData)
break
default:
alert('no such rule type' + rule['type'])
}
}
console.log('run rule result:', result)
return result
}
......@@ -69,9 +109,9 @@ export function runRule(rule:any, deviceMap:Record<string, any>){
* 函数“runAllEnableRule”在给定的设备映射上运行所有启用的规则。
* @param deviceMap - 将设备名称映射到其相应信息或数据的记录对象。
*/
export function runAllEnableRule(deviceMap:Record<string, any>){
rules.forEach((item:any) => {
if(item['enable'].toString() === 'true') {
export function runAllEnableRule(deviceMap: Record<string, any>) {
rules.forEach((item: any) => {
if (item['enable'].toString() === 'true') {
runRule(item, deviceMap)
}
})
......@@ -82,8 +122,8 @@ export function runAllEnableRule(deviceMap:Record<string, any>){
* @param {string} id - “id”参数是一个字符串,表示规则的唯一标识符。它用于在“rules”数组中查找规则。
* @param deviceMap - “deviceMap”参数是一个记录对象,它将设备名称映射到其相应的信息或状态。它用于提供运行规则所需的数据。
*/
export function runRuleById(id:string, deviceMap:Record<string, any>){
let rule = rules.find((item:any) => item.id == id)
export function runRuleById(id: string, deviceMap: Record<string, any>) {
let rule = rules.find((item: any) => item.id == id)
runRule(rule, deviceMap)
}
......@@ -91,17 +131,17 @@ export function runRuleById(id:string, deviceMap:Record<string, any>){
* 函数“testRule”将规则对象作为输入,从规则中提取测试数据,从规则的函数字符串创建一个新函数,然后使用测试数据作为参数执行该函数。
* @param {any} rule - “rule”参数是包含有关特定规则的信息的对象。
*/
export function testRule(rule:any){
export function testRule(rule: any) {
let inputData = []
let runFunc = null
if (rule){
for (let input of rule.inputs){
if (rule) {
for (let input of rule.inputs) {
inputData.push(input['testData'])
}
runFunc = new Function( "return " + rule.func)
runFunc = new Function("return " + rule.func)
try {
runFunc()(...inputData)
}catch (e){
} catch (e) {
alert(e)
}
}
......@@ -111,7 +151,39 @@ export function testRule(rule:any){
* 函数“testRuleById”通过 ID 查找规则,然后测试该规则。
* @param {string} id - “id”参数是一个字符串,表示规则的唯一标识符。
*/
export function testRuleById(id:string){
let rule = rules.find((item:any) => item.id == id)
export function testRuleById(id: string) {
let rule = rules.find((item: any) => item.id == id)
testRule(rule)
}
\ No newline at end of file
}
export function runJS(rule: any, inputData: any) {
const funcBody = "(data)=>{ "+ rule['func']+"}"
const runFunc = new Function("return " + funcBody)
try {
return runFunc()(inputData)
} catch (e) {
alert(e)
}
}
export function runLua(rule: any, inputData: any) {
try {
// 创建Lua状态
let codestring = `
return function (data)
${rule['func']}
end
`
let luaFunction = fengari.load(codestring)
let result = luaFunction().call(inputData);
return result
} catch (e) {
alert(e)
}
}
......@@ -3,4 +3,5 @@ declare module '*.vue' {
import { ComponentOptions } from 'vue'
const componentOptions: ComponentOptions
export default componentOptions
}
\ No newline at end of file
}
declare module 'fengari-web';
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment