Commit f6eb0d285ce5cbdfdd0ebf3dd018f880dfbcafbe

Authored by loveumiko
1 parent b71a47e6

feat: 新增规则链库功能

... ... @@ -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 169 return defHttp.delete(
170 170 {
171 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 202 { joinPrefix: false }
175 203 );
... ...
... ... @@ -136,6 +136,7 @@ export const useGenDynamicForm = () => {
136 136 fieldTypeMap.clear();
137 137 const formSchema = schemas.map((item) => {
138 138 const { functionName, identifier, dataType } = item;
  139 + console.log(item, 'item');
139 140 const { type } = dataType || {};
140 141
141 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 5 v-bind="$attrs"
6 6 width="30rem"
7 7 @register="register"
8   - title="添加规则链"
  8 + :title="ruleTile"
9 9 @ok="handleSuccess"
10 10 @close="handleClose"
11 11 >
... ... @@ -17,49 +17,73 @@
17 17 </template>
18 18 <script setup lang="ts">
19 19 import { BasicModal, useModalInner } from '/@/components/Modal';
20   - import { ExecuteReportRecord } from '/@/api/export/model/exportModel';
21 20 import { useForm, BasicForm } from '/@/components/Form';
22 21 import { formSchema } from './config';
23 22 import { createRuleChine } from '/@/api/ruleengine/ruleengineApi';
24 23 import { useMessage } from '/@/hooks/web/useMessage';
  24 + import { ref, unref } from 'vue';
25 25
26 26 const emit = defineEmits(['register', 'success']);
27 27
28 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 33 labelWidth: 120,
32 34 schemas: formSchema,
33 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 54 const handleClose = () => {
44 55 closeModal();
45 56 };
46 57
47 58 const handleSuccess = async () => {
48   - console.log(1, '1', getFieldsValue());
49 59 await validate();
50 60 const record = getFieldsValue();
51 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 87 handleClose();
64 88 emit('success');
65 89 };
... ...
... ... @@ -16,7 +16,7 @@ export const columns: BasicColumn[] = [
16 16 width: 200,
17 17 },
18 18 {
19   - title: '是否链',
  19 + title: '是否链',
20 20 dataIndex: 'root',
21 21 slots: {
22 22 customRender: 'root',
... ... @@ -41,3 +41,20 @@ export const searchFormSchema: FormSchema[] = [
41 41 export const encode = (string: string) => {
42 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 <a-button type="primary" @click="handleAdd"> 新增规则链 </a-button>
7 7 </Authority>
8 8 <!-- <Authority>
  9 + <a-button type="primary" @click="handleImport"> 导入规则链 </a-button>
  10 + </Authority> -->
  11 + <!-- <Authority>
9 12 <Popconfirm
10 13 title="您确定要批量删除数据"
11 14 ok-text="确定"
... ... @@ -23,10 +26,37 @@
23 26 <TableAction
24 27 :actions="[
25 28 {
26   - label: '查看',
  29 + label: '打开规则链',
27 30 icon: 'ant-design:eye-outlined',
28 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 61 label: '删除',
32 62 icon: 'ant-design:delete-outlined',
... ... @@ -42,12 +72,25 @@
42 72 </template>
43 73 </BasicTable>
44 74 <RuleChainModal @register="registerModal" @success="handleSuccess" />
  75 +
  76 + <!-- <ChainDetailDrawer @register="registerDrawer" /> -->
45 77 </div>
46 78 </template>
47 79 <script lang="ts" setup>
48 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 94 import { useModal } from '/@/components/Modal';
52 95 import { Authority } from '/@/components/Authority';
53 96 import { Tag } from 'ant-design-vue';
... ... @@ -55,11 +98,19 @@
55 98 import { useMessage } from '/@/hooks/web/useMessage';
56 99 import { usePermission } from '/@/hooks/web/usePermission';
57 100 import { useRouter } from 'vue-router';
  101 + // import { ChainDetailDrawer } from './chainDetail/index';
  102 + // import { useDrawer } from '/@/components/Drawer';
58 103
59 104 const [registerTable, { reload, setProps }] = useTable({
60 105 title: '规则链库',
61 106 api: getRuleChinsList,
  107 + rowKey: (record) => record.id.id,
62 108 columns,
  109 + pagination: true,
  110 + useSearchForm: true,
  111 + showTableSetting: true,
  112 + bordered: true,
  113 + showIndexColumn: false,
63 114 formConfig: {
64 115 labelWidth: 120,
65 116 schemas: searchFormSchema,
... ... @@ -68,17 +119,19 @@
68 119 pageField: 'page',
69 120 listField: 'data',
70 121 },
71   - pagination: true,
72   - useSearchForm: true,
73   - showTableSetting: true,
74   - bordered: true,
75   - showIndexColumn: false,
76 122 beforeFetch(params) {
77 123 Reflect.set(params, 'page', params.page - 1);
78 124 Reflect.set(params, 'sortProperty', 'createdTime');
79 125 Reflect.set(params, 'sortOrder', 'DESC');
80 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 135 actionColumn: {
83 136 width: 200,
84 137 title: '操作',
... ... @@ -90,12 +143,23 @@
90 143
91 144 const [registerModal, { openModal }] = useModal();
92 145
  146 + // const [registerDrawer, { openDrawer }] = useDrawer();
  147 +
93 148 const handleSuccess = () => {
94 149 reload();
95 150 };
96 151
97 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 165 const { createMessage } = useMessage();
... ... @@ -103,13 +167,53 @@
103 167 const router = useRouter();
104 168
105 169 const handleView = (record: Recordable) => {
106   - const hasDetailPermission = hasPermission('rule:chain:detail');
  170 + const hasDetailPermission = hasPermission(RuleChainPermisssion.DETAIL);
107 171 if (hasDetailPermission) {
108 172 const boardId = encode(record.id.id);
109 173 router.push(`/rule/chain/${boardId}`);
110 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 217 const handleDeleteOrBatchDelete = async (record: Recordable) => {
114 218 setProps({
115 219 loading: true,
... ...