addItem.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <template>
  2. <el-dialog :title="ruleForm.id ? '修改控制策略' : '添加控制策略'" v-model="isShowDialog" width="650px">
  3. <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="auto" status-icon>
  4. <el-form-item label="标题" prop="title" style="width: 388px">
  5. <el-input clearable v-model="ruleForm.title" />
  6. </el-form-item>
  7. <el-form-item label="类型" prop="types">
  8. <el-radio-group v-model="ruleForm.types">
  9. <el-radio :label="1">手动</el-radio>
  10. <el-radio :label="2">自动</el-radio>
  11. </el-radio-group>
  12. </el-form-item>
  13. <el-form-item label="状态" prop="status">
  14. <el-radio-group v-model="ruleForm.status">
  15. <el-radio :label="1">启用</el-radio>
  16. <el-radio :label="2">禁用</el-radio>
  17. </el-radio-group>
  18. </el-form-item>
  19. <el-form-item label="说明" style="width: 388px">
  20. <el-input v-model="ruleForm.description" type="textarea" />
  21. </el-form-item>
  22. <el-form-item label="参数配置" prop="param">
  23. <div style="width: 100%">
  24. <div class="param-wrap" v-for="(item, index) in ruleForm.param" :key="index">
  25. <el-input clearable placeholder="key" v-model="item.key" />
  26. <el-input clearable placeholder="标题" v-model="item.title" />
  27. <el-select v-model="item.types" placeholder="请选择数据类型">
  28. <el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
  29. <el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
  30. </el-option-group>
  31. </el-select>
  32. <el-button v-if="index === ruleForm.param.length - 1" @click="plusParam()">
  33. <el-icon>
  34. <ele-Plus />
  35. </el-icon>
  36. </el-button>
  37. <el-button v-else @click="minusParam(index)">
  38. <el-icon>
  39. <ele-Minus />
  40. </el-icon>
  41. </el-button>
  42. </div>
  43. </div>
  44. </el-form-item>
  45. </el-form>
  46. <div class="form-btn-wrap">
  47. <el-button type="primary" @click="onSubmit(ruleFormRef)"> 提交 </el-button>
  48. </div>
  49. </el-dialog>
  50. </template>
  51. <script lang="ts" setup>
  52. import { ref } from "vue";
  53. import api from "/@/api/device";
  54. import policyApi from "/@/api/modules/policy";
  55. import axios from "axios";
  56. import { ElMessage } from "element-plus";
  57. import type { FormInstance } from "element-plus";
  58. import { getToken } from "/@/utils/auth";
  59. import { v4 as uuid } from "uuid";
  60. import { getRuleServerOrigin } from "/@/utils/origin";
  61. interface RuleForm {
  62. id: any;
  63. title: string;
  64. types: number;
  65. status: number;
  66. description: string;
  67. param: any[];
  68. flowId: string;
  69. }
  70. const emit = defineEmits(["getList"]);
  71. const headers = {
  72. Authorization: "Bearer " + getToken(),
  73. };
  74. const isShowDialog = ref(false);
  75. const ruleFormRef = ref<FormInstance>();
  76. const ruleForm = ref<RuleForm>({
  77. id: null,
  78. title: "",
  79. types: 2,
  80. status: 1,
  81. description: "",
  82. param: [
  83. {
  84. key: "",
  85. title: "",
  86. types: "",
  87. },
  88. ],
  89. flowId: "",
  90. });
  91. // 数据类型下拉数据
  92. const typeData = ref([]);
  93. const validateParam = (rule: any, value: any, callback: any) => {
  94. if (value === "") {
  95. callback(new Error("请输入参数配置"));
  96. } else if (value) {
  97. verification(value)
  98. .then(() => {
  99. callback();
  100. })
  101. .catch((e: string) => {
  102. callback(new Error(e));
  103. });
  104. } else {
  105. callback();
  106. }
  107. };
  108. const verification = (data: any) => {
  109. return new Promise(function (resolve, reject) {
  110. try {
  111. data.forEach((item: any, indexs: number) => {
  112. if (!item.key && !item.title && !item.types) {
  113. throw "参数配置未完善,请进行完善";
  114. }
  115. if (!item.key) {
  116. throw "第" + (indexs + 1) + "个参数配置的key未完善,请进行完善";
  117. } else if (!item.title) {
  118. throw "第" + (indexs + 1) + "个参数配置的标题未完善,请进行完善";
  119. } else if (!item.types) {
  120. throw "第" + (indexs + 1) + "个参数配置的数据类型未完善,请进行完善";
  121. }
  122. });
  123. } catch (e) {
  124. return reject(e);
  125. }
  126. resolve("成功");
  127. });
  128. };
  129. const rules = ref({
  130. title: [{ required: true, message: "请输入标题", trigger: "blur" }],
  131. types: [
  132. {
  133. required: true,
  134. message: "请输入说明",
  135. trigger: "change",
  136. },
  137. ],
  138. status: [{ required: true, message: "请选择状态", trigger: "blur" }],
  139. param: [{ required: true, validator: validateParam, trigger: "change" }],
  140. });
  141. const onSubmit = async (formEl: FormInstance | undefined) => {
  142. if (!formEl) return;
  143. await formEl.validate();
  144. if (!ruleForm.value.id) {
  145. const id = uuid();
  146. await axios.post(
  147. getRuleServerOrigin("/api/v1/rules/" + id),
  148. {
  149. ruleChain: {
  150. id: id,
  151. name: ruleForm.value.title,
  152. root: true,
  153. additionalInfo: {
  154. description: ruleForm.value.description,
  155. layoutX: "130",
  156. layoutY: "220",
  157. },
  158. },
  159. metadata: {
  160. nodes: [
  161. {
  162. id: "node_2",
  163. additionalInfo: {
  164. layoutX: 606,
  165. layoutY: 424,
  166. },
  167. type: "log",
  168. name: "日志",
  169. debugMode: true,
  170. configuration: {
  171. jsScript: "return 'Incoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
  172. },
  173. },
  174. ],
  175. endpoints: [],
  176. connections: [],
  177. },
  178. },
  179. { headers }
  180. );
  181. ruleForm.value.flowId = id;
  182. } else {
  183. // 找到规则
  184. const { data } = (await axios.get(getRuleServerOrigin("/api/v1/rules/" + ruleForm.value.flowId), { headers }).catch(() => {
  185. ElMessage.error("规则不存在");
  186. })) as any;
  187. // 修改名称和说明
  188. data.ruleChain.name = ruleForm.value.title;
  189. data.ruleChain.additionalInfo.description = ruleForm.value.description;
  190. // 保存
  191. await axios.post(getRuleServerOrigin("/api/v1/rules/" + ruleForm.value.flowId), data, { headers });
  192. }
  193. const theApi = ruleForm.value.id ? policyApi.edit : policyApi.add;
  194. await theApi(ruleForm.value);
  195. ElMessage.success("操作成功");
  196. resetForm();
  197. isShowDialog.value = false;
  198. emit("getList");
  199. };
  200. const resetForm = () => {
  201. ruleFormRef.value && ruleFormRef.value.resetFields();
  202. ruleForm.value.param = [
  203. {
  204. key: "",
  205. title: "",
  206. types: "",
  207. },
  208. ];
  209. };
  210. const plusParam = () => {
  211. ruleForm.value.param.push({
  212. key: "",
  213. title: "",
  214. types: "",
  215. });
  216. };
  217. const minusParam = (index: number) => {
  218. ruleForm.value.param.splice(index, 1);
  219. };
  220. // 打开弹窗
  221. const openDialog = (row?: any) => {
  222. resetForm();
  223. if (row) {
  224. policyApi.detail(row.id).then((res: any) => {
  225. const { id, title, types, description, paramData, flowId, status } = res.data;
  226. ruleForm.value = {
  227. id: id,
  228. title: title,
  229. types: types,
  230. status: status,
  231. description: description,
  232. param: paramData,
  233. flowId: flowId,
  234. };
  235. });
  236. }
  237. api.product.getDataType({ status: -1 }).then((res: any) => {
  238. const data: any = Object.values(res.dataType);
  239. data.forEach((item: any, index: number) => {
  240. if (index == 0) {
  241. data[index]["label"] = "基础类型";
  242. data[index]["options"] = item;
  243. } else {
  244. data[index]["label"] = "扩展类型";
  245. data[index]["options"] = item.filter((i: any) => ["enum", "array", "object"].indexOf(i.type) === -1);
  246. }
  247. });
  248. typeData.value = data || [];
  249. });
  250. isShowDialog.value = true;
  251. };
  252. defineExpose({ openDialog });
  253. </script>
  254. <style lang="scss" scoped>
  255. .param-wrap {
  256. display: flex;
  257. justify-content: space-between;
  258. align-items: center;
  259. margin-bottom: 10px;
  260. .el-input,
  261. .el-select {
  262. width: 150px;
  263. }
  264. }
  265. .el-icon {
  266. margin-right: 0 !important;
  267. }
  268. ::v-deep .el-dialog__body {
  269. position: relative;
  270. }
  271. .form-btn-wrap {
  272. position: absolute;
  273. bottom: 20px;
  274. right: 20px;
  275. display: flex;
  276. justify-content: flex-end;
  277. align-items: center;
  278. width: 100%;
  279. }
  280. </style>