Ben Lin
2024-10-22 e4f79a7e36214e5836cb0e667b3ffbd3db45456d
src/views/tigerprojects/system/lowcode/composition/index.vue
@@ -1,88 +1,273 @@
<!--
 * @Description: 通用组合页面,左边是树,右边是配置
 * @Author: Ben Lin
 * @version:
 * @Date: 2024-06-18 23:30:30
 * @LastEditors: Ben Lin
 * @LastEditTime: 2024-10-21 23:03:27
-->
<template>
  <div>
    <BasicTable @register="registerTable">
  <PageWrapper
    contentFullHeight
    contentClass="flex"
    :title="pageTitle"
    :content="pageContent"
    @back="goBack"
  >
    <Suspense class="w-1/4 xl:w-1/5">
      <LeftTree @select="NodeSelect" @deletenode="delCallback" />
    </Suspense>
    <Suspense>
      <div class="w-3/4 xl:w-4/5 p-5">
        <CarGridNav v-if="showNav" :configType="configType" :nodes="nodes">
          <template #[item] v-for="item in otherSlots" :key="item">
            <!-- 自定义内容 -->
            <div class="h-full" style="height: 400px">
              <FlowChartView :data="routeData" @init="init" />
            </div>
          </template>
        </CarGridNav>
        <Config
          v-if="showConfig"
          :configType="configType"
          :OtherTableName="OtherTableName"
          @success="configSuccess"
        />
      </div>
    </Suspense>
    <!-- <BasicTable class="w-3/4 xl:w-4/5" @register="registerTable">
      <template #toolbar>
        <a-button type="primary" @click="handleCreate"> 新增部门 </a-button>
        <a-button type="primary" @click="handleCreate" preIcon="add_02|svg"> 新增 </a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'action'">
          <TableAction
            :actions="[
              {
                icon: 'clarity:note-edit-line',
                onClick: handleEdit.bind(null, record),
              },
              {
                icon: 'ant-design:delete-outlined',
                color: 'error',
                popConfirm: {
                  title: '是否确认删除',
                  placement: 'left',
                  confirm: handleDelete.bind(null, record),
                },
              },
            ]"
          />
          <TableAction :actions="createActions(record)" />
        </template>
      </template>
    </BasicTable>
    <DeptModal @register="registerModal" @success="handleSuccess" />
  </div>
    </BasicTable> -->
    <!-- <normalDrawer @register="registerDrawer" @success="handleSuccess" /> -->
    <Suspense>
      <CustModal
        @register="registerCust"
        @success="custSuccess"
        :type="cType"
        :detailSlots="dtlSlots"
        :entityName="entityName"
      >
        <!-- 用插槽自定义多表单 -->
        <template #[item.name] v-for="item in dtlSlots" :key="item.name">
          <BasicForm @register="useFormData[item.name][0]" v-if="useFormData[item.name]">
            <!-- 用插槽自定义弹出选择框 -->
            <template #[name]="{ field }" v-for="name in item.slots" :key="name">
              <a-button
                class="mt-1 ml-1"
                size="small"
                @click="handleCustClick(field)"
                :preIcon="item.preIcons[name]"
              />
              <GeneralModal
                @register="useModalData[name][0]"
                @success="(d, u) => handleEntSuccess(d, u, item.name)"
              />
            </template>
          </BasicForm>
          <!-- 自定义内容 -->
        </template>
      </CustModal>
    </Suspense>
  </PageWrapper>
</template>
<script lang="ts" setup>
  import { BasicTable, useTable, TableAction } from '@/components/Table';
  import { getDeptList } from '@/api/demo/system';
  import { PageWrapper } from '@/components/Page';
  import { useModal } from '@/components/Modal';
  import DeptModal from './DeptModal.vue';
  import GeneralModal from '/@/views/components/GeneralModal.vue';
  import CarGridNav from './CarGridNav.vue';
  import Config from './Config.vue';
  import LeftTree from './LeftTree.vue';
  import CustModal from '/@/views/components/CustModal.vue';
  import { OpenCustModal, initRoute } from '../data';
  import { Ref, VNode, onMounted, provide, ref, unref } from 'vue';
  import { FlowChartView } from '/@/components/FlowChart';
  import { useRoute } from 'vue-router';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { useTabs } from '/@/hooks/web/useTabs';
  import { isNullOrUnDef } from '/@/utils/is';
  import { useGo } from '/@/hooks/web/usePage';
  import { useMessage } from '/@/hooks/web/useMessage';
  import LogicFlow from '@logicflow/core';
  import { columns, searchFormSchema } from './dept.data';
  defineOptions({ name: '工单工艺绑定' });
  defineOptions({ name: 'DeptManagement' });
  const { notification, createErrorModal } = useMessage();
  const go = useGo();
  const route = useRoute();
  const { setTitle, refreshPage } = useTabs();
  // const objParams = ref(JSON.parse(decodeURI(route.params?.id as string))); //ref(JSON.parse(history.state.obj))
  const routeParams = ref(JSON.parse(decodeURI(route.params?.id as string)));
  // 从sessionStorage中读取参数并转换回对象
  const savedParams = sessionStorage.getItem(`${routeParams.value.sName}_params`);
  const objParams = savedParams ? ref(JSON.parse(decodeURI(savedParams))) : ref({});
  const entityName = ref(routeParams.value.Name);
  const useModalData = ref({}); //表单中插槽渲染按钮打开模态框useModal方法
  const useFormData = ref({});
  const cType = ref('');
  const dtlSlots = ref([] as any[]);
  const otherSlots = ref<any[]>([]);
  const selectVals = ref({});
  const dense = isNullOrUnDef(objParams.value.dense) ? ref(false) : ref(objParams.value.dense);
  const pageTitle = ref(objParams.value.pageTitle);
  const pageContent = ref(objParams.value.pageContent);
  const colSlots = ref<any>(objParams.value.colSlots);
  const selectedNodes = ref([]);
  const isMounted = ref(false);
  const showNav = ref(false);
  const showConfig = ref(false);
  const showOtherTable = ref(false);
  const configType = ref('');
  const OtherTableName = ref('');
  const nodes = ref([]);
  const routeData = ref({
    nodes: [],
    edges: [],
  });
  const custImport = ref<any>(null);
  const [registerCust] = useModal();
  provide<Ref<any>>('objParams', objParams);
  provide<Ref<any>>('selectedNodes', nodes);
  setTitle(objParams.value.Title); //设置标签页标题
  const [registerModal, { openModal }] = useModal();
  const [registerTable, { reload }] = useTable({
    title: '部门列表',
    api: getDeptList,
    columns,
    formConfig: {
      labelWidth: 120,
      schemas: searchFormSchema,
    },
    pagination: false,
    striped: false,
    useSearchForm: true,
    showTableSetting: true,
    bordered: true,
    showIndexColumn: false,
    canResize: false,
    actionColumn: {
      width: 80,
      title: '操作',
      dataIndex: 'action',
      // slots: { customRender: 'action' },
      fixed: undefined,
    },
  /**
   * @description: 页面左侧点击返回链接时的操作
   * @return {*}
   */
  function goBack() {
    if (!isNullOrUnDef(custImport.value)) {
      const [{ GetHomeUrl }] = custImport.value['default']();
      // 本例的效果时点击返回始终跳转到账号列表页,实际应用时可返回上一页
      go(GetHomeUrl({ colSlots: colSlots.value, sName:objParams.value.firstSessionName  }));
    }
  }
  // function handleAdd(){
  //   console.log('handleAdd');
  // }
  onMounted(async () => {
    isMounted.value = false;
    /* 动态import实体名.ts的自定义方法 */
    try {
      custImport.value = await import(`../entityts/${entityName.value}.ts`);
      if (custImport.value['default']) {
        otherSlots.value = custImport.value['default']()[0]['GetSlots']();
      }
      isMounted.value = true;
    } catch (e) {
      console.log(e);
    }
  });
  function handleCreate() {
    openModal(true, {
      isUpdate: false,
    });
  const currlf = ref(null) as Ref<LogicFlow | null>;
  /**
   * @description: 工艺路线初始化,特殊页面自定义内容
   * @param {*} lf
   * @return {*}
   */
  async function init(lf, rotId) {
    initRoute(lf, rotId, routeData, currlf, objParams.value.rotType);
  }
  function handleEdit(record: Recordable) {
    openModal(true, {
      record,
      isUpdate: true,
    });
  /**
   * @description: 选择节点时根据返回的事件参数显示隐藏相应组件
   * @param {*} e
   * @return {*}
   */
  function NodeSelect(e) {
    showConfig.value = e.showConfig;
    showOtherTable.value = e.showOtherTable;
    showNav.value = e.showNav;
    configType.value = e.type;
    OtherTableName.value = objParams.value.OtherTableName;
    nodes.value = e.nodes;
    routeData.value = {
      nodes: [],
      edges: [],
    };
    /* 自定义内容,只有显示工艺路线的组合页面会进来 */
    if (e.nodes[0].type == 'Route') {
      let _rotId = e.nodes[0].code;
      if (objParams.value.rotType == 'Wo') {
        _rotId = e.nodes[0].wo;
      }
      initRoute(currlf, _rotId, routeData, currlf, objParams.value.rotType);
    }
  }
  function handleDelete(record: Recordable) {
    console.log(record);
  /**
   * @description: 删除节点后回调
   * @param {*} node
   * @return {*}
   */
  function delCallback(node) {
    refreshPage();
  }
  function handleSuccess() {
    reload();
  /**
   * @description: 保存配置成功返回方法
   * @return {*}
   */
  function configSuccess() {
    notification.success({ message: '成功保存行为配置数据' });
  }
  /**
   * @description: 弹出框确定返回
   * @param {*} d
   * @return {*}
   */
  function custSuccess(d) {
    // reload();
  }
  /**
   * @description: 各表单内弹出选择框选择成功后方法
   * @param {*} d
   * @param {*} u
   * @param {*} item
   * @return {*}
   */
  function handleEntSuccess(d, u, item) {
    /* 动态import实体名.ts的自定义方法 */
    try {
      import(`../entityts/${cType.value}.ts`).then((m) => {
        const [{ GetSelectSuccess }] = m.default();
        var values = GetSelectSuccess(d, u);
        selectVals.value = values; //保存弹出框选择的结果
        let _val = {};
        d.returnFieldName.map((x) => {
          _val[x] = values[x];
        });
        useFormData.value[item][1].setFieldsValue(_val);
      });
    } catch (e) {}
  }
  /**
   * @description: 打开自定义模态框
   * @param {*} item
   * @return {*}
   */
  function handleCustClick(item) {
    OpenCustModal(
      useModalData.value[item][1].openModal, //带入openModal方法
      cType.value,
      item,
      [],
      // selectVals.value['ROUTE_CODE'],
    ); //[openRvModal], selectVals.value['ID']这是自定义参数,按实际需求
  }
</script>
<style lang="less">
.vben-page-wrapper .vben-page-wrapper-content {
    margin: 1px;
}
</style>