index.vue 8.17 KB
<template>
  <div>
    <BasicTable @register="registerTable">
      <template #toolbar>
        <Authority>
          <a-button type="primary" @click="handleAdd"> 新增规则链 </a-button>
        </Authority>
        <Upload :show-upload-list="false" accept=".json," :customRequest="handleImport">
          <Button type="primary" :loading="importLoading"> 导入规则链 </Button>
        </Upload>
        <Authority>
          <Popconfirm
            title="您确定要批量删除数据"
            ok-text="确定"
            cancel-text="取消"
            @confirm="handleDeleteOrBatchDelete(null)"
          >
            <a-button color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
          </Popconfirm>
        </Authority>
      </template>
      <template #root="{ record }">
        <Tag :color="record.root ? 'green' : 'red'"> {{ record.root ? '是' : '否' }}</Tag>
      </template>
      <template #action="{ record }">
        <TableAction
          :actions="[
            {
              label: '打开规则链',
              icon: 'ant-design:eye-outlined',
              onClick: handleView.bind(null, record),
            },
            {
              label: '编辑',
              icon: 'clarity:note-edit-line',
              onClick: handleBussinessModal.bind(null, record),
            },
          ]"
          :dropDownActions="[
            {
              label: '设置为根规则链',
              icon: 'ant-design:gateway-outlined',
              color: 'error',
              ifShow: !record.root,
              popConfirm: {
                title: '是否确认设置成根规则链',
                confirm: handleSettingRoot.bind(null, record),
              },
            },
            {
              label: '导出规则链',
              icon: 'ant-design:vertical-align-bottom-outlined',
              onClick: handleExport.bind(null, record),
            },
            {
              label: '删除',
              icon: 'ant-design:delete-outlined',
              color: 'error',
              ifShow: !record.root,
              popConfirm: {
                title: '是否确认删除',
                confirm: handleDeleteOrBatchDelete.bind(null, record.id.id),
              },
            },
          ]"
        />
      </template>
    </BasicTable>
    <RuleChainModal @register="registerModal" @success="handleSuccess" />

    <!-- <ChainDetailDrawer @register="registerDrawer" /> -->
  </div>
</template>
<script lang="ts" setup>
  import { BasicTable, useTable, TableAction } from '/@/components/Table';
  import {
    RuleChainPermisssion,
    columns,
    encode,
    exportJSONFile,
    searchFormSchema,
    paseJSON,
  } from './config/config.data';
  import {
    deleteRuleChine,
    getRuleChinsList,
    exportRuleChine,
    settingRootChine,
    importRuleChine,
    createRuleChine,
  } from '/@/api/ruleengine/ruleengineApi';
  import { useModal } from '/@/components/Modal';
  import { Authority } from '/@/components/Authority';
  import { Tag, Button, Upload, Popconfirm } from 'ant-design-vue';
  import { RuleChainModal } from './component/index';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { usePermission } from '/@/hooks/web/usePermission';
  import { useRouter } from 'vue-router';
  import { ref } from 'vue';
  import { isObject } from '/@/utils/is';
  const [registerModal, { openModal }] = useModal();
  const { createMessage } = useMessage();
  const { hasPermission } = usePermission();
  const router = useRouter();

  const isEmptyObject = (value: any) => isObject(value) && !Object.keys(value).length;
  const importLoading = ref<boolean>(false);
  const hasBatchDelete = ref<boolean>(true);

  const beforeFetch = (params) => {
    Reflect.set(params, 'page', params.page - 1);
    Reflect.set(params, 'sortProperty', 'createdTime');
    Reflect.set(params, 'sortOrder', 'DESC');
    return params;
  };

  const rowSelection = () => {
    return {
      type: 'checkbox',
      getCheckboxProps: (record: Recordable) => {
        return { disabled: record.root };
      },
      onChange(rowKeys: string[]) {
        hasBatchDelete.value = rowKeys.length <= 0;
      },
    };
  };

  const [registerTable, { reload, setProps, getSelectRowKeys, clearSelectedRowKeys }] = useTable({
    title: '规则链库',
    api: getRuleChinsList,
    rowKey: (record) => record.id.id,
    columns,
    pagination: true,
    useSearchForm: true,
    showTableSetting: true,
    bordered: true,
    showIndexColumn: false,
    formConfig: {
      labelWidth: 120,
      schemas: searchFormSchema,
    },
    resizeHeightOffset: 40,
    canResize: true,
    fetchSetting: {
      pageField: 'page',
      totalField: 'totalElements',
      listField: 'data',
    },
    beforeFetch: (params) => beforeFetch(params),
    rowSelection: rowSelection() as any,
    actionColumn: {
      width: 220,
      title: '操作',
      dataIndex: 'action',
      slots: { customRender: 'action' },
      fixed: 'right',
    },
  });

  const handleSuccess = () => {
    reload();
  };

  const handleAdd = () => {
    openModal(true, {
      text: '创建规则链',
    });
  };

  const handleBussinessModal = (record) => {
    openModal(true, {
      text: '编辑规则链',
      record,
    });
  };

  const handleView = (record: Recordable) => {
    const hasDetailPermission = hasPermission(RuleChainPermisssion.DETAIL);
    if (hasDetailPermission) {
      const boardId = encode(record.id.id);
      router.push(`/rule/chain/${boardId}`);
    } else createMessage.warning('没有权限');
  };

  const handleImport = (data: { file: File }) => {
    const fileReader = new FileReader();

    fileReader.onload = async () => {
      const { flag, data } = paseJSON(fileReader.result as string);
      if (!flag) {
        createMessage.warning('JSON解析失败,请导入正确的JSON~');
        return;
      }
      try {
        importLoading.value = true;

        Object.keys(data || {}).forEach((key) => {
          const value = (data || {})[key];
          if (value && isEmptyObject(value)) {
            (data || {})[key] = [];
          }
        });
        const { ruleChain, metadata } = data as any;

        // 创建规则链
        const value = await createRuleChine(ruleChain);
        const { id } = value;

        const values = {
          ruleChainId: id,
          ...metadata,
        };
        // 导入规则链详情nodes的东西
        const rules = await importRuleChine(values);

        rules
          ? createMessage.success('导入成功~')
          : createMessage.error('JSON解析失败,请导入正确的JSON~');

        rules && reload();
      } catch (error) {
        throw error;
      } finally {
        importLoading.value = false;
      }
    };

    fileReader.readAsText(data.file, 'utf-8');
  };

  const handleExport = async (record: Recordable) => {
    if (!record) return;
    const { additionalInfo, name, type, firstRuleNodeId, root, debugMode, configuration } =
      record || {};
    const { firstNodeIndex, nodes, connections, ruleChainConnections } = await exportRuleChine(
      record.id.id
    );

    const node = nodes.map((item) => {
      return {
        ...item,
        id: undefined,
        ruleChainId: undefined,
      };
    });
    const value = {
      ruleChain: { additionalInfo, name, type, firstRuleNodeId, root, debugMode, configuration },
      metadata: { firstNodeIndex, nodes: node, connections, ruleChainConnections },
    };
    exportJSONFile(value, name);
  };

  const handleSettingRoot = async (record) => {
    setProps({
      loading: true,
    });
    try {
      await settingRootChine(record.id.id);
      createMessage.success('设置成功');
    } finally {
      setProps({
        loading: false,
      });
      reload();
    }
  };

  const handleDeleteOrBatchDelete = async (id: string | null) => {
    setProps({
      loading: true,
    });
    try {
      if (!id) {
        const ids = getSelectRowKeys();
        await Promise.all(ids.map((item) => deleteRuleChine(item)));
        return;
      }
      await deleteRuleChine(id);
    } finally {
      setProps({
        loading: false,
      });
      createMessage.success('删除成功');
      clearSelectedRowKeys();
      reload();
    }
  };
</script>