|
@@ -0,0 +1,297 @@
|
|
|
+<template>
|
|
|
+ <el-dialog :title="ruleForm.id ? '修改控制策略' : '添加控制策略'" v-model="isShowDialog" width="650px">
|
|
|
+ <el-form
|
|
|
+ ref="ruleFormRef"
|
|
|
+ :model="ruleForm"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="auto"
|
|
|
+ status-icon
|
|
|
+ >
|
|
|
+ <el-form-item label="标题" prop="title" style="width: 388px;">
|
|
|
+ <el-input clearable v-model="ruleForm.title" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="类型" prop="types">
|
|
|
+ <el-radio-group v-model="ruleForm.types">
|
|
|
+ <el-radio :label="1">手动</el-radio>
|
|
|
+ <el-radio :label="2">自动</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="说明" prop="description" style="width: 388px;">
|
|
|
+ <el-input v-model="ruleForm.description" type="textarea" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="参数配置" prop="param">
|
|
|
+ <div style="width: 100%;">
|
|
|
+ <div class="param-wrap" v-for="(item, index) in ruleForm.param" :key="index">
|
|
|
+ <el-input clearable placeholder="key" v-model="item.key" />
|
|
|
+ <el-input clearable placeholder="标题" v-model="item.title" />
|
|
|
+ <el-select v-model="item.types" placeholder="请选择数据类型">
|
|
|
+ <el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
|
|
|
+ <el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
|
|
|
+ </el-option-group>
|
|
|
+ </el-select>
|
|
|
+ <el-button v-if="index === ruleForm.param.length -1" @click="plusParam()">
|
|
|
+ <el-icon>
|
|
|
+ <ele-Plus />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button v-else @click="minusParam(index)">
|
|
|
+ <el-icon>
|
|
|
+ <ele-Minus />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div class="form-btn-wrap">
|
|
|
+ <el-button type="primary" @click="onSubmit(ruleFormRef)"> 提交 </el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref } from 'vue'
|
|
|
+import api from '/@/api/device';
|
|
|
+import policyApi from '/@/api/policy';
|
|
|
+import axios from 'axios';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import type { FormInstance } from 'element-plus'
|
|
|
+import { getToken } from "/@/utils/auth";
|
|
|
+import { v4 as uuid } from "uuid";
|
|
|
+
|
|
|
+interface RuleForm {
|
|
|
+ id: any
|
|
|
+ title: string
|
|
|
+ types: number
|
|
|
+ description: string,
|
|
|
+ param: any[],
|
|
|
+ flowId: string,
|
|
|
+}
|
|
|
+
|
|
|
+const emit = defineEmits(['getList']);
|
|
|
+
|
|
|
+const headers = {
|
|
|
+ Authorization: 'Bearer ' + getToken(),
|
|
|
+};
|
|
|
+const isShowDialog = ref(false);
|
|
|
+const ruleFormRef = ref<FormInstance>()
|
|
|
+const ruleForm = ref<RuleForm>({
|
|
|
+ id: null,
|
|
|
+ title: '',
|
|
|
+ types: 2,
|
|
|
+ description: '',
|
|
|
+ param: [ {
|
|
|
+ key: "",
|
|
|
+ title: "",
|
|
|
+ types: ""
|
|
|
+ }],
|
|
|
+ flowId: ''
|
|
|
+})
|
|
|
+
|
|
|
+// 数据类型下拉数据
|
|
|
+const typeData = ref([]);
|
|
|
+const validateParam = (rule: any, value: any, callback: any) => {
|
|
|
+ if (value === '') {
|
|
|
+ callback(new Error('请输入参数配置'))
|
|
|
+ } else if (value) {
|
|
|
+ verification(value).then(() => {
|
|
|
+ callback()
|
|
|
+ })
|
|
|
+ .catch((e:string) => {
|
|
|
+ callback(new Error(e))
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const verification = (data:any) => {
|
|
|
+ return new Promise(function(resolve, reject) {
|
|
|
+ try {
|
|
|
+ data.forEach((item:any, indexs:number) => {
|
|
|
+ if (!item.key && !item.title && !item.types) {
|
|
|
+ throw '参数配置未完善,请进行完善'
|
|
|
+ }
|
|
|
+ if (!item.key) {
|
|
|
+ throw '第' + (indexs + 1) + '个参数配置的key未完善,请进行完善'
|
|
|
+ } else if (!item.title) {
|
|
|
+ throw '第' + (indexs + 1) + '个参数配置的标题未完善,请进行完善'
|
|
|
+ } else if (!item.types) {
|
|
|
+ throw '第' + (indexs + 1) + '个参数配置的数据类型未完善,请进行完善'
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ return reject(e)
|
|
|
+ }
|
|
|
+ resolve('成功')
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const rules = ref({
|
|
|
+ title: [
|
|
|
+ { required: true, message: '请输入标题', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ types: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入说明',
|
|
|
+ trigger: 'change',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ description: [
|
|
|
+ { required: true, message: '请输入描述', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ param: [{ required: true, validator: validateParam, trigger: 'change' }],
|
|
|
+})
|
|
|
+
|
|
|
+const onSubmit = async (formEl: FormInstance | undefined) => {
|
|
|
+ if (!formEl) return
|
|
|
+ await formEl.validate();
|
|
|
+ if (!ruleForm.value.id) {
|
|
|
+ const id = uuid();
|
|
|
+ await axios.post(
|
|
|
+ import.meta.env.VITE_RULE_SERVER_URL + "/api/v1/rules/" + id,
|
|
|
+ {
|
|
|
+ ruleChain: {
|
|
|
+ id: id,
|
|
|
+ name: ruleForm.value.title,
|
|
|
+ root: true,
|
|
|
+ additionalInfo: {
|
|
|
+ description: ruleForm.value.description,
|
|
|
+ layoutX: "130",
|
|
|
+ layoutY: "220",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ metadata: {
|
|
|
+ nodes: [{
|
|
|
+ "id": "node_2",
|
|
|
+ "additionalInfo": {
|
|
|
+ "layoutX": 606,
|
|
|
+ "layoutY": 424
|
|
|
+ },
|
|
|
+ "type": "log",
|
|
|
+ "name": "日志",
|
|
|
+ "debugMode": true,
|
|
|
+ "configuration": {
|
|
|
+ "jsScript": "return 'Incoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
|
|
+ }
|
|
|
+ }],
|
|
|
+ endpoints: [],
|
|
|
+ connections: [],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ { headers }
|
|
|
+ );
|
|
|
+ ruleForm.value.flowId = id;
|
|
|
+ } else {
|
|
|
+ // 找到规则
|
|
|
+ const { data } = (await axios.get(import.meta.env.VITE_RULE_SERVER_URL + "/api/v1/rules/" + ruleForm.value.flowId, { headers }).catch(() => {
|
|
|
+ ElMessage.error("规则不存在");
|
|
|
+ })) as any;
|
|
|
+
|
|
|
+ // 修改名称和说明
|
|
|
+ data.ruleChain.name = ruleForm.value.title;
|
|
|
+ data.ruleChain.additionalInfo.description = ruleForm.value.description;
|
|
|
+
|
|
|
+ // 保存
|
|
|
+ await axios.post(import.meta.env.VITE_RULE_SERVER_URL + "/api/v1/rules/" + ruleForm.value.flowId, data, { headers });
|
|
|
+ }
|
|
|
+ const theApi = ruleForm.value.id ? policyApi.edit : policyApi.add;
|
|
|
+
|
|
|
+ await theApi(ruleForm.value);
|
|
|
+
|
|
|
+ ElMessage.success('操作成功');
|
|
|
+ resetForm();
|
|
|
+ isShowDialog.value = false;
|
|
|
+ emit('getList');
|
|
|
+}
|
|
|
+
|
|
|
+const resetForm = () => {
|
|
|
+ ruleFormRef.value && ruleFormRef.value.resetFields();
|
|
|
+
|
|
|
+ ruleForm.value.param = [{
|
|
|
+ key: "",
|
|
|
+ title: "",
|
|
|
+ types: ""
|
|
|
+ }]
|
|
|
+}
|
|
|
+
|
|
|
+const plusParam = () => {
|
|
|
+ ruleForm.value.param.push({
|
|
|
+ key: '',
|
|
|
+ title: '',
|
|
|
+ types: ''
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const minusParam = (index:number) => {
|
|
|
+ ruleForm.value.param.splice(index, 1);
|
|
|
+}
|
|
|
+
|
|
|
+// 打开弹窗
|
|
|
+const openDialog = (row?: any) => {
|
|
|
+ resetForm();
|
|
|
+ if (row) {
|
|
|
+ policyApi.detail(row.id).then((res: any) => {
|
|
|
+ const { id, title, types, description, paramData, flowId } = res.data;
|
|
|
+ ruleForm.value = {
|
|
|
+ id: id,
|
|
|
+ title: title,
|
|
|
+ types: types,
|
|
|
+ description: description,
|
|
|
+ param: paramData,
|
|
|
+ flowId: flowId
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ api.product.getDataType({ status: -1 }).then((res: any) => {
|
|
|
+ const data:any = Object.values(res.dataType)
|
|
|
+ data.forEach((item:any, index:number) => {
|
|
|
+ if (index == 0) {
|
|
|
+ data[index]['label'] = '基础类型';
|
|
|
+ data[index]['options'] = item;
|
|
|
+ } else {
|
|
|
+ data[index]['label'] = '扩展类型';
|
|
|
+ data[index]['options'] = item.filter((i:any) => ['enum', 'array', 'object'].indexOf(i.type) === -1);
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+ typeData.value = data || [];
|
|
|
+ });
|
|
|
+ isShowDialog.value = true;
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+defineExpose({ openDialog })
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .param-wrap {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ .el-input,
|
|
|
+ .el-select {
|
|
|
+ width: 150px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .el-icon {
|
|
|
+ margin-right: 0!important;
|
|
|
+ }
|
|
|
+ ::v-deep .el-dialog__body {
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ .form-btn-wrap {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 20px;
|
|
|
+ right: 20px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+</style>
|