Commit f6eb0d285ce5cbdfdd0ebf3dd018f880dfbcafbe

Authored by loveumiko
1 parent b71a47e6

feat: 新增规则链库功能

@@ -165,11 +165,39 @@ export const createRuleChine = (params) => { @@ -165,11 +165,39 @@ export const createRuleChine = (params) => {
165 * 删除规则链 165 * 删除规则链
166 */ 166 */
167 167
168 -export const deleteRuleChine = (params) => { 168 +export const deleteRuleChine = (id) => {
169 return defHttp.delete( 169 return defHttp.delete(
170 { 170 {
171 url: `${ScreenManagerApi.RULE_CHAIN}/`, 171 url: `${ScreenManagerApi.RULE_CHAIN}/`,
172 - params, 172 + params: id,
  173 + },
  174 + { joinPrefix: false }
  175 + );
  176 +};
  177 +
  178 +/**
  179 + * 导出规则链
  180 + */
  181 +
  182 +export const exportRuleChine = (id) => {
  183 + return defHttp.get(
  184 + {
  185 + url: `${ScreenManagerApi.RULE_CHAIN}/`,
  186 + params: id + '/metadata',
  187 + },
  188 + { joinPrefix: false }
  189 + );
  190 +};
  191 +
  192 +/**
  193 + * 设置根规则链接
  194 + */
  195 +
  196 +export const settingRootChine = (id) => {
  197 + return defHttp.post(
  198 + {
  199 + url: `${ScreenManagerApi.RULE_CHAIN}/`,
  200 + params: id + '/root',
173 }, 201 },
174 { joinPrefix: false } 202 { joinPrefix: false }
175 ); 203 );
@@ -136,6 +136,7 @@ export const useGenDynamicForm = () => { @@ -136,6 +136,7 @@ export const useGenDynamicForm = () => {
136 fieldTypeMap.clear(); 136 fieldTypeMap.clear();
137 const formSchema = schemas.map((item) => { 137 const formSchema = schemas.map((item) => {
138 const { functionName, identifier, dataType } = item; 138 const { functionName, identifier, dataType } = item;
  139 + console.log(item, 'item');
139 const { type } = dataType || {}; 140 const { type } = dataType || {};
140 141
141 fieldTypeMap.set(identifier!, dataType!.type); 142 fieldTypeMap.set(identifier!, dataType!.type);
  1 +<template>
  2 + <div>属性</div>
  3 +</template>
  4 +
  5 +<script setup lang="ts"></script>
  6 +
  7 +<style lang="less" scoped></style>
  1 +<template>
  2 + <div>警告</div>
  3 +</template>
  4 +
  5 +<script setup lang="ts"></script>
  6 +
  7 +<style lang="less" scoped></style>
  1 +import ChainDetailDrawer from './index.vue';
  2 +export { ChainDetailDrawer };
  1 +<template>
  2 + <BasicDrawer
  3 + v-bind="$attrs"
  4 + isDetail
  5 + @register="register"
  6 + destroyOnClose
  7 + @close="closeDrawer"
  8 + :title="deviceDetail.alias || deviceDetail.name"
  9 + width="80%"
  10 + >
  11 + <Tabs v-model:activeKey="activeKey" :size="size">
  12 + <TabPane key="1" tab="详情">
  13 + <div>详情</div>
  14 + </TabPane>
  15 + <TabPane key="2" tab="属性">
  16 + <Attribute />
  17 + </TabPane>
  18 + <TabPane key="3" tab="最新遥测数据"><div>最新遥测数据</div></TabPane>
  19 + <TabPane key="4" tab="警告">
  20 + <div>警告</div>
  21 + </TabPane>
  22 + <TabPane key="5" tab="事件">
  23 + <div>事件</div>
  24 + </TabPane>
  25 + <!-- 网关设备并且场家是TBox -->
  26 + <TabPane key="6" tab="关联">
  27 + <div>关联</div>
  28 + </TabPane>
  29 + <!-- 网关设备并且是TBox -->
  30 +
  31 + <TabPane key="7" tab="审计日志">
  32 + <div>审计日志</div>
  33 + </TabPane>
  34 + </Tabs>
  35 + </BasicDrawer>
  36 +</template>
  37 +<script lang="ts" setup>
  38 + import { ref } from 'vue';
  39 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  40 +
  41 + import { Tabs, TabPane } from 'ant-design-vue';
  42 + import { DeviceRecord } from '/@/api/device/model/deviceModel';
  43 +
  44 + import Attribute from './component/Attribute.vue';
  45 +
  46 + // defineProps({});
  47 +
  48 + // defineEmits([]);
  49 +
  50 + const activeKey = ref('1');
  51 + const size = ref('small');
  52 + const deviceDetail = ref<DeviceRecord>({} as unknown as DeviceRecord);
  53 + // 详情回显
  54 + const [register] = useDrawerInner(async (data) => {
  55 + console.log(data, 'data');
  56 + });
  57 + const closeDrawer = () => {
  58 + activeKey.value = '1';
  59 + };
  60 +</script>
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 v-bind="$attrs" 5 v-bind="$attrs"
6 width="30rem" 6 width="30rem"
7 @register="register" 7 @register="register"
8 - title="添加规则链" 8 + :title="ruleTile"
9 @ok="handleSuccess" 9 @ok="handleSuccess"
10 @close="handleClose" 10 @close="handleClose"
11 > 11 >
@@ -17,49 +17,73 @@ @@ -17,49 +17,73 @@
17 </template> 17 </template>
18 <script setup lang="ts"> 18 <script setup lang="ts">
19 import { BasicModal, useModalInner } from '/@/components/Modal'; 19 import { BasicModal, useModalInner } from '/@/components/Modal';
20 - import { ExecuteReportRecord } from '/@/api/export/model/exportModel';  
21 import { useForm, BasicForm } from '/@/components/Form'; 20 import { useForm, BasicForm } from '/@/components/Form';
22 import { formSchema } from './config'; 21 import { formSchema } from './config';
23 import { createRuleChine } from '/@/api/ruleengine/ruleengineApi'; 22 import { createRuleChine } from '/@/api/ruleengine/ruleengineApi';
24 import { useMessage } from '/@/hooks/web/useMessage'; 23 import { useMessage } from '/@/hooks/web/useMessage';
  24 + import { ref, unref } from 'vue';
25 25
26 const emit = defineEmits(['register', 'success']); 26 const emit = defineEmits(['register', 'success']);
27 27
28 const { createMessage } = useMessage(); 28 const { createMessage } = useMessage();
29 29
30 - const [registerForm, { getFieldsValue, validate }] = useForm({ 30 + const ruleTile = ref();
  31 +
  32 + const [registerForm, { getFieldsValue, validate, setFieldsValue }] = useForm({
31 labelWidth: 120, 33 labelWidth: 120,
32 schemas: formSchema, 34 schemas: formSchema,
33 showActionButtonGroup: false, 35 showActionButtonGroup: false,
34 }); 36 });
35 37
36 - const [register, { setModalProps, closeModal }] = useModalInner(  
37 - async (data: { record: ExecuteReportRecord }) => {  
38 - setModalProps({ loading: true });  
39 - console.log(data, 'record');  
40 - }  
41 - ); 38 + const updateValue = ref({});
  39 + const isUpdate = ref<boolean>(true);
  40 +
  41 + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
  42 + setModalProps({ loading: true });
  43 + const { text, record } = data || {};
  44 + console.log(data, 'data');
  45 + isUpdate.value = record ? true : false;
  46 + ruleTile.value = text;
  47 + const { name, additionalInfo, debugMode } = record || {};
  48 + const { description } = additionalInfo || {};
  49 + updateValue.value = record;
  50 + unref(isUpdate) && setFieldsValue({ name, debugMode, description });
  51 + setModalProps({ loading: false });
  52 + });
42 53
43 const handleClose = () => { 54 const handleClose = () => {
44 closeModal(); 55 closeModal();
45 }; 56 };
46 57
47 const handleSuccess = async () => { 58 const handleSuccess = async () => {
48 - console.log(1, '1', getFieldsValue());  
49 await validate(); 59 await validate();
50 const record = getFieldsValue(); 60 const record = getFieldsValue();
51 const { description, debugMode, name } = record; 61 const { description, debugMode, name } = record;
52 - const form = {  
53 - additionalInfo: {  
54 - description,  
55 - },  
56 - debugMode,  
57 - name,  
58 - type: 'CORE',  
59 - }; 62 + if (!isUpdate.value) {
  63 + const form = {
  64 + additionalInfo: {
  65 + description,
  66 + },
  67 + debugMode,
  68 + name,
  69 + type: 'CORE',
  70 + };
  71 + await createRuleChine(form);
  72 + createMessage.success('添加成功');
  73 + } else {
  74 + const value = {
  75 + ...updateValue.value,
  76 + additionalInfo: {
  77 + description,
  78 + },
  79 + debugMode,
  80 + name,
  81 + };
  82 + console.log(value, 'value');
  83 + await createRuleChine(value);
  84 + createMessage.success('编辑成功');
  85 + }
60 86
61 - await createRuleChine(form);  
62 - createMessage.success('添加成功');  
63 handleClose(); 87 handleClose();
64 emit('success'); 88 emit('success');
65 }; 89 };
@@ -16,7 +16,7 @@ export const columns: BasicColumn[] = [ @@ -16,7 +16,7 @@ export const columns: BasicColumn[] = [
16 width: 200, 16 width: 200,
17 }, 17 },
18 { 18 {
19 - title: '是否链', 19 + title: '是否链',
20 dataIndex: 'root', 20 dataIndex: 'root',
21 slots: { 21 slots: {
22 customRender: 'root', 22 customRender: 'root',
@@ -41,3 +41,20 @@ export const searchFormSchema: FormSchema[] = [ @@ -41,3 +41,20 @@ export const searchFormSchema: FormSchema[] = [
41 export const encode = (string: string) => { 41 export const encode = (string: string) => {
42 return encodeURIComponent(string); 42 return encodeURIComponent(string);
43 }; 43 };
  44 +
  45 +export const exportJSONFile = (value: Recordable, name: string) => {
  46 + const blob = new Blob([JSON.stringify(value, null, 2)], { type: 'text/json' });
  47 + const objectURL = URL.createObjectURL(blob);
  48 + const element = document.createElement('a');
  49 + element.href = objectURL;
  50 + element.download = `${name}.json`;
  51 + element.style.display = 'none';
  52 + document.body.appendChild(element);
  53 + element.click();
  54 + element.remove();
  55 + URL.revokeObjectURL(objectURL);
  56 +};
  57 +
  58 +export enum RuleChainPermisssion {
  59 + DETAIL = 'rule:chain:detail',
  60 +}
@@ -6,6 +6,9 @@ @@ -6,6 +6,9 @@
6 <a-button type="primary" @click="handleAdd"> 新增规则链 </a-button> 6 <a-button type="primary" @click="handleAdd"> 新增规则链 </a-button>
7 </Authority> 7 </Authority>
8 <!-- <Authority> 8 <!-- <Authority>
  9 + <a-button type="primary" @click="handleImport"> 导入规则链 </a-button>
  10 + </Authority> -->
  11 + <!-- <Authority>
9 <Popconfirm 12 <Popconfirm
10 title="您确定要批量删除数据" 13 title="您确定要批量删除数据"
11 ok-text="确定" 14 ok-text="确定"
@@ -23,10 +26,37 @@ @@ -23,10 +26,37 @@
23 <TableAction 26 <TableAction
24 :actions="[ 27 :actions="[
25 { 28 {
26 - label: '查看', 29 + label: '打开规则链',
27 icon: 'ant-design:eye-outlined', 30 icon: 'ant-design:eye-outlined',
28 onClick: handleView.bind(null, record), 31 onClick: handleView.bind(null, record),
29 }, 32 },
  33 + // {
  34 + // label: '详情',
  35 + // icon: 'ant-design:field-time-outlined',
  36 + // onClick: handleDetail.bind(null, record),
  37 + // },
  38 + {
  39 + label: '编辑',
  40 + icon: 'clarity:note-edit-line',
  41 + onClick: handleBussinessModal.bind(null, record),
  42 + },
  43 + ]"
  44 + :dropDownActions="[
  45 + {
  46 + label: '设置为根规则链',
  47 + icon: 'ant-design:gateway-outlined',
  48 + color: 'error',
  49 + ifShow: !record.root,
  50 + popConfirm: {
  51 + title: '是否确认设置成根规则链',
  52 + confirm: handleSettingRoot.bind(null, record),
  53 + },
  54 + },
  55 + {
  56 + label: '导出规则链',
  57 + icon: 'ant-design:vertical-align-bottom-outlined',
  58 + onClick: handleExport.bind(null, record),
  59 + },
30 { 60 {
31 label: '删除', 61 label: '删除',
32 icon: 'ant-design:delete-outlined', 62 icon: 'ant-design:delete-outlined',
@@ -42,12 +72,25 @@ @@ -42,12 +72,25 @@
42 </template> 72 </template>
43 </BasicTable> 73 </BasicTable>
44 <RuleChainModal @register="registerModal" @success="handleSuccess" /> 74 <RuleChainModal @register="registerModal" @success="handleSuccess" />
  75 +
  76 + <!-- <ChainDetailDrawer @register="registerDrawer" /> -->
45 </div> 77 </div>
46 </template> 78 </template>
47 <script lang="ts" setup> 79 <script lang="ts" setup>
48 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 80 import { BasicTable, useTable, TableAction } from '/@/components/Table';
49 - import { columns, encode, searchFormSchema } from './config/config.data';  
50 - import { deleteRuleChine, getRuleChinsList } from '/@/api/ruleengine/ruleengineApi'; 81 + import {
  82 + RuleChainPermisssion,
  83 + columns,
  84 + encode,
  85 + exportJSONFile,
  86 + searchFormSchema,
  87 + } from './config/config.data';
  88 + import {
  89 + deleteRuleChine,
  90 + getRuleChinsList,
  91 + exportRuleChine,
  92 + settingRootChine,
  93 + } from '/@/api/ruleengine/ruleengineApi';
51 import { useModal } from '/@/components/Modal'; 94 import { useModal } from '/@/components/Modal';
52 import { Authority } from '/@/components/Authority'; 95 import { Authority } from '/@/components/Authority';
53 import { Tag } from 'ant-design-vue'; 96 import { Tag } from 'ant-design-vue';
@@ -55,11 +98,19 @@ @@ -55,11 +98,19 @@
55 import { useMessage } from '/@/hooks/web/useMessage'; 98 import { useMessage } from '/@/hooks/web/useMessage';
56 import { usePermission } from '/@/hooks/web/usePermission'; 99 import { usePermission } from '/@/hooks/web/usePermission';
57 import { useRouter } from 'vue-router'; 100 import { useRouter } from 'vue-router';
  101 + // import { ChainDetailDrawer } from './chainDetail/index';
  102 + // import { useDrawer } from '/@/components/Drawer';
58 103
59 const [registerTable, { reload, setProps }] = useTable({ 104 const [registerTable, { reload, setProps }] = useTable({
60 title: '规则链库', 105 title: '规则链库',
61 api: getRuleChinsList, 106 api: getRuleChinsList,
  107 + rowKey: (record) => record.id.id,
62 columns, 108 columns,
  109 + pagination: true,
  110 + useSearchForm: true,
  111 + showTableSetting: true,
  112 + bordered: true,
  113 + showIndexColumn: false,
63 formConfig: { 114 formConfig: {
64 labelWidth: 120, 115 labelWidth: 120,
65 schemas: searchFormSchema, 116 schemas: searchFormSchema,
@@ -68,17 +119,19 @@ @@ -68,17 +119,19 @@
68 pageField: 'page', 119 pageField: 'page',
69 listField: 'data', 120 listField: 'data',
70 }, 121 },
71 - pagination: true,  
72 - useSearchForm: true,  
73 - showTableSetting: true,  
74 - bordered: true,  
75 - showIndexColumn: false,  
76 beforeFetch(params) { 122 beforeFetch(params) {
77 Reflect.set(params, 'page', params.page - 1); 123 Reflect.set(params, 'page', params.page - 1);
78 Reflect.set(params, 'sortProperty', 'createdTime'); 124 Reflect.set(params, 'sortProperty', 'createdTime');
79 Reflect.set(params, 'sortOrder', 'DESC'); 125 Reflect.set(params, 'sortOrder', 'DESC');
80 return params; 126 return params;
81 }, 127 },
  128 + rowSelection: {
  129 + type: 'checkbox',
  130 + getCheckboxProps: (record: Recordable) => {
  131 + console.log(record, 'record');
  132 + return { disabled: record.root };
  133 + },
  134 + },
82 actionColumn: { 135 actionColumn: {
83 width: 200, 136 width: 200,
84 title: '操作', 137 title: '操作',
@@ -90,12 +143,23 @@ @@ -90,12 +143,23 @@
90 143
91 const [registerModal, { openModal }] = useModal(); 144 const [registerModal, { openModal }] = useModal();
92 145
  146 + // const [registerDrawer, { openDrawer }] = useDrawer();
  147 +
93 const handleSuccess = () => { 148 const handleSuccess = () => {
94 reload(); 149 reload();
95 }; 150 };
96 151
97 const handleAdd = () => { 152 const handleAdd = () => {
98 - openModal(true); 153 + openModal(true, {
  154 + text: '创建规则链',
  155 + });
  156 + };
  157 +
  158 + const handleBussinessModal = (record) => {
  159 + openModal(true, {
  160 + text: '编辑规则链',
  161 + record,
  162 + });
99 }; 163 };
100 164
101 const { createMessage } = useMessage(); 165 const { createMessage } = useMessage();
@@ -103,13 +167,53 @@ @@ -103,13 +167,53 @@
103 const router = useRouter(); 167 const router = useRouter();
104 168
105 const handleView = (record: Recordable) => { 169 const handleView = (record: Recordable) => {
106 - const hasDetailPermission = hasPermission('rule:chain:detail'); 170 + const hasDetailPermission = hasPermission(RuleChainPermisssion.DETAIL);
107 if (hasDetailPermission) { 171 if (hasDetailPermission) {
108 const boardId = encode(record.id.id); 172 const boardId = encode(record.id.id);
109 router.push(`/rule/chain/${boardId}`); 173 router.push(`/rule/chain/${boardId}`);
110 } else createMessage.warning('没有权限'); 174 } else createMessage.warning('没有权限');
111 }; 175 };
112 176
  177 + // const handleRowClick = (record) => {
  178 + // openDrawer(true, { record });
  179 + // console.log('点击行', record);
  180 + // };
  181 +
  182 + // const handleDetail = (record) => {
  183 + // console.log(record, '详情');
  184 + // };
  185 +
  186 + // const handleImport = () => {};
  187 +
  188 + const handleExport = async (record: Recordable) => {
  189 + if (!record) return;
  190 + const { additionalInfo, name, type, firstRuleNodeId, root, debugMode, configuration } =
  191 + record || {};
  192 + const { firstNodeIndex, nodes, connections, ruleChainConnections } = await exportRuleChine(
  193 + record.id.id
  194 + );
  195 + const value = {
  196 + ruleChain: { additionalInfo, name, type, firstRuleNodeId, root, debugMode, configuration },
  197 + metadata: { firstNodeIndex, nodes, connections, ruleChainConnections },
  198 + };
  199 + exportJSONFile(value, name);
  200 + };
  201 +
  202 + const handleSettingRoot = async (record) => {
  203 + setProps({
  204 + loading: true,
  205 + });
  206 + try {
  207 + await settingRootChine(record.id.id);
  208 + createMessage.success('设置成功');
  209 + } finally {
  210 + setProps({
  211 + loading: false,
  212 + });
  213 + }
  214 + reload();
  215 + };
  216 +
113 const handleDeleteOrBatchDelete = async (record: Recordable) => { 217 const handleDeleteOrBatchDelete = async (record: Recordable) => {
114 setProps({ 218 setProps({
115 loading: true, 219 loading: true,