Browse Source

部分功能更改,流程修改完善

cz 1 year ago
parent
commit
1ea4294fb3

+ 1 - 0
package.json

@@ -27,6 +27,7 @@
     "@antv/x6-plugin-transform": "^2.1.6",
     "@antv/x6-vue-shape": "^2.0.11",
     "@imengyu/vue3-context-menu": "^1.3.5",
+    "@infectoone/vue-ganttastic": "^2.3.2",
     "@tinymce/tinymce-vue": "^5.1.0",
     "@vue-flow/additional-components": "^1.3.3",
     "@vue-flow/core": "^1.18.2",

+ 0 - 1
src/components/byTable/ElementsMapping.vue

@@ -52,7 +52,6 @@ export default defineComponent({
   },
   setup(props) {
     const { proxy } = getCurrentInstance();
-    console.log(props, "awdwa");
     const getCellList = computed(() => {
       return props.cellList.filter((cell) => cell && Object.keys(cell).length);
     });

+ 3 - 3
src/components/process/SF/CostControl.vue

@@ -703,14 +703,14 @@ const formConfig = computed(() => {
       type: "treeSelect",
       prop: "companyId",
       label: "业务公司",
-      data: treeData.value,
+      data: proxy.useUserStore().allDict["tree_company_data"],
       propsTreeLabel: "deptName",
       propsTreeValue: "deptId",
       itemWidth: 25,
       fn: (val) => {
         getDeptData(val);
       },
-      disabled: true,
+      disabled: false,
       isShow:
         isShowAtt("companyId", "mainObj") &&
         currentCostTypeData.value.name != "采购货款",
@@ -723,7 +723,7 @@ const formConfig = computed(() => {
       propsTreeLabel: "deptName",
       propsTreeValue: "deptId",
       itemWidth: 25,
-      disabled: true,
+      disabled: false,
       isShow: isShowAtt("deptId", "mainObj"),
     },
     {

+ 4 - 0
src/main.js

@@ -36,6 +36,9 @@ const uploadUrl =
   import.meta.env.VITE_APP_UPLOAD_API +
   import.meta.env.VITE_APP_UPLOAD_BASE_API + '/open/fileInfo/upload'
 
+// 甘特图
+import ganttastic from '@infectoone/vue-ganttastic'
+
 import {
   useDict
 } from '@/utils/dict'
@@ -149,6 +152,7 @@ app.use(plugins)
 app.use(i18n)
 app.use(elementIcons)
 app.use(print)
+app.use(ganttastic)
 directive(app)
 
 // 使用element-plus 并且设置全局的大小

+ 4 - 2
src/views/EHSD/saleContract/PriceSheetDetail.vue

@@ -171,14 +171,16 @@
                         <el-input-number v-model="product.price" placeholder="" style="width: 100%" :precision="2" :controls="false" :min="1"
                                          onmousewheel="return false;" disabled />
                       </el-form-item> -->
-                      单价:<span>{{product.price}}</span>
+                      <span v-if="dataType=='1'">工厂供货价:{{product.prodPrice}}</span>
+                      <span v-else> 单价:{{product.price}}</span>
                     </el-col>
                     <el-col :span="6" style="padding-left:15px">
                       <!-- <el-form-item label="总价" class="margin-b-0" @click.stop>
                         <el-input-number v-model="product.amount" placeholder="" style="width: 100%" :precision="2" :controls="false" :min="1"
                                          onmousewheel="return false;" disabled />
                       </el-form-item> -->
-                      总价:<span>{{product.amount}}</span>
+                      <span v-if="dataType=='1'"> 最终单价:{{product.price}}</span>
+                      <span v-else>总价:{{product.amount}}</span>
                     </el-col>
 
                   </el-row>

+ 33 - 14
src/views/EHSD/saleContract/contractEHSD/index.vue

@@ -3,6 +3,11 @@
     <div class="content">
       <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" :selectConfig="selectConfig"
                :statConfig="statConfig" :onMoreSearch="false" @moreSearch="clickMoreSearch" highlight-current-row :action-list="[
+                {
+                text: '导出Excel',
+                action: () => exportExcel(),
+                disabled: false,
+              },
           {
             text: '新建',
             action: () => newContract(),
@@ -59,17 +64,21 @@
         <template #product="{item}">
           <div style="width: 100%">
             <el-popover placement="top-start" :width="400" trigger="hover" @show="onShowProductData(item)">
-              <div style="display:flex;margin-bottom:20px;align-items:center" v-for="i in  productData" :key="i.id">
-                <div style="width:60px">
-                  <img :src="i.productImgUrl" alt="" class="pic" @click="handleClickFile(i.productImgUrl)">
-                </div>
-                <div style="width:calc(100% - 60px)">
-                  <div>产品编码:{{i.productCode}}</div>
-                  <div>产品名称:{{i.productName}}</div>
-                  <div>产品尺寸:{{i.productLength}}cm*{{i.productWidth}}cm*{{i.productHeight}}cm</div>
-                  <div>产品颜色:{{i.productColor}}</div>
-                  <div>产品数量:{{i.quantity}}</div>
-                  <div>生产完成数量:{{i.finishQuantity}}</div>
+              <div style="overflow:auto;height:300px">
+                <div style="display:flex;margin-bottom:20px;align-items:center" v-for="i in  productData" :key="i.id">
+                  <div style="width:60px">
+                    <img :src="i.productImgUrl" alt="" class="pic" @click="handleClickFile(i.productImgUrl)">
+                  </div>
+                  <div style="width:calc(100% - 60px)">
+                    <div>产品编码:{{i.productCode}}</div>
+                    <div>产品名称:{{i.productName}}</div>
+                    <div>产品尺寸:{{i.productLength}}cm*{{i.productWidth}}cm*{{i.productHeight}}cm</div>
+                    <div>产品颜色:{{i.productColor}}</div>
+                    <div>产品数量:{{i.quantity}}</div>
+                    <div>生产完成数量:{{i.finishQuantity || 0}}</div>
+                    <div>出货数量:{{i.saleOutboundQuantity || 0}}</div>
+                    <div>未出货数量:{{i.notSaleOutboundQuantity || 0}}</div>
+                  </div>
                 </div>
               </div>
               <template #reference>
@@ -711,6 +720,7 @@ const statConfig = computed(() => [
   //   ],
   // },
 ]);
+
 const config = computed(() => {
   return [
     {
@@ -1667,9 +1677,9 @@ const clickUpdate = (row) => {
 };
 
 const PdfDom = ref(null);
-const exportExcel = () => {
-  PdfDom.value.exportExcel();
-};
+// const exportExcel = () => {
+//   PdfDom.value.exportExcel();
+// };
 
 const formData = reactive({
   recordsFormData: {},
@@ -2383,6 +2393,15 @@ const objectSpanMethod = ({ rowIndex, columnIndex }) => {
     };
   }
 };
+
+const exportExcel = () => {
+  proxy.msgTip("正在导出,请稍后", 2);
+  proxy
+    .postTwo("/contract/excelExport", sourceList.value.pagination)
+    .then((res) => {
+      proxy.downloadFile(res, "销售订单.xlsx");
+    });
+};
 </script>
 
 <style lang="scss" scoped>

+ 98 - 0
src/views/JST/shopManage/index.vue

@@ -18,6 +18,40 @@
 
       </byTable>
     </div>
+    <!-- 甘特图 -->
+    <g-gantt-chart chart-start="2021-07-01 00:01" chart-end="2021-07-31 23:59" color-scheme="grove" precision="day" bar-start="myBeginDate"
+                   bar-end="myEndDate" date-format="YYYY-MM-DD HH:mm" @click-bar="onMouseupBar" @dragend-bar="onDragBar" v-if="false">
+      <!-- 大标题 -->
+      <template #upper-timeunit="{label,value}">
+        <div>{{label}}</div>
+      </template>
+      <!-- 小标题 -->
+      <template #timeunit="{label,value}">
+        <div>{{label.split('.')[0]}}</div>
+      </template>
+
+      <!-- 提示 -->
+      <template #bar-tooltip="{bar}">
+
+        <div> aa</div>
+
+      </template>
+      <!-- 左侧标题 -->
+      <template #current-time-label="{}">
+
+        <div> 左侧标题</div>
+
+      </template>
+
+      <g-gantt-row :bars="row1BarList">
+        <!-- 内部label -->
+        <template #bar-label="{bar}">
+          <div> bb</div>
+        </template>
+      </g-gantt-row>
+      <g-gantt-row :bars="row2BarList"></g-gantt-row>
+    </g-gantt-chart>
+
     <el-dialog :title="modalType == 'add' ? '添加店铺' : '编辑店铺'" v-model="dialogVisible" width="500px" destroy-on-close>
       <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
       </byForm>
@@ -34,6 +68,70 @@
 <script setup>
 import byTable from "@/components/byTable/index";
 import byForm from "@/components/byForm/index";
+const row1BarList = ref([
+  {
+    myBeginDate: "2021-07-13 13:00",
+    myEndDate: "2021-07-13 19:00",
+    ganttBarConfig: {
+      // each bar must have a nested ganttBarConfig object ...
+      id: "unique-id-1", // ... and a unique "id" property
+      label: "任务一",
+    },
+  },
+  {
+    myBeginDate: "2021-07-13 18:00",
+    myEndDate: "2021-07-13 21:00",
+    ganttBarConfig: {
+      // each bar must have a nested ganttBarConfig object ...
+      id: "unique-id-3", // ... and a unique "id" property
+      label: "任务3",
+      style: {
+        // arbitrary CSS styling for your bar
+        background: "#e09b69",
+        borderRadius: "20px",
+        color: "black",
+      },
+    },
+  },
+  {
+    myBeginDate: "2021-07-16 18:00",
+    myEndDate: "2021-07-17 21:00",
+    ganttBarConfig: {
+      // each bar must have a nested ganttBarConfig object ...
+      id: "unique-id-4", // ... and a unique "id" property
+      label: "任务4",
+      style: {
+        // arbitrary CSS styling for your bar
+        background: "#e09b69",
+        borderRadius: "20px",
+        color: "black",
+      },
+    },
+  },
+]);
+const row2BarList = ref([
+  {
+    myBeginDate: "2021-07-13 00:00",
+    myEndDate: "2021-07-14 02:00",
+    ganttBarConfig: {
+      id: "another-unique-id-2",
+      hasHandles: true,
+      label: "任务二",
+      style: {
+        // arbitrary CSS styling for your bar
+        background: "#e09b69",
+        borderRadius: "20px",
+        color: "black",
+      },
+    },
+  },
+]);
+const onMouseupBar = ({ bar, e, datetime }) => {
+  console.log(bar, e, datetime, "awdadw");
+};
+const onDragBar = ({ bar, e }) => {
+  console.log(bar, e, "awdadw");
+};
 const { proxy } = getCurrentInstance();
 const loading = ref(false);
 const submitLoading = ref(false);

+ 29 - 28
src/views/finance/fundManage/accountPayment/index.vue

@@ -317,34 +317,35 @@ const config = computed(() => {
                   getDtl(row);
                 },
               }
-            : {
-                attrs: {
-                  label: "冲销",
-                  type: "danger",
-                  text: true,
-                },
-                el: "button",
-                click(item) {
-                  ElMessageBox.confirm(
-                    "冲销后,已生成的资金流水数据会被删除,且关联的数据状态会由“已打款”退回至“未打款”,并支持重新打款。是否继续?",
-                    "提示",
-                    {
-                      confirmButtonText: "继续",
-                      cancelButtonText: "取消",
-                      type: "warning",
-                    }
-                  )
-                    .then(() => {
-                      rowData.value = item;
-                      formCancelledOutData.data = {
-                        accountPaymentId: item.id,
-                        remark: "",
-                      };
-                      openCancelledOut.value = true;
-                    })
-                    .catch(() => {});
-                },
-              },
+            : {},
+          // : {
+          //     attrs: {
+          //       label: "冲销",
+          //       type: "danger",
+          //       text: true,
+          //     },
+          //     el: "button",
+          //     click(item) {
+          //       ElMessageBox.confirm(
+          //         "冲销后,已生成的资金流水数据会被删除,且关联的数据状态会由“已打款”退回至“未打款”,并支持重新打款。是否继续?",
+          //         "提示",
+          //         {
+          //           confirmButtonText: "继续",
+          //           cancelButtonText: "取消",
+          //           type: "warning",
+          //         }
+          //       )
+          //         .then(() => {
+          //           rowData.value = item;
+          //           formCancelledOutData.data = {
+          //             accountPaymentId: item.id,
+          //             remark: "",
+          //           };
+          //           openCancelledOut.value = true;
+          //         })
+          //         .catch(() => {});
+          //     },
+          //   },
           // {
           //   attrs: {
           //     label: "打印",

+ 1 - 0
src/views/index.vue

@@ -388,6 +388,7 @@ const pushProcessApproval = (row) => {
           flowKey: row.flowKey,
           id: row.id,
           processType: nodeType == 1 ? 30 : 10,
+          version: row.version,
           businessId: row.businessId,
         },
       });

+ 33 - 0
src/views/process/dealWith/backlog.vue

@@ -12,6 +12,11 @@
         <template #slotName="{ item }">
           {{ item.createTime }}
         </template>
+        <template #nodeType="{item}">
+          <div style="width:100%">
+            <span :class="{csNode:item.nodeHandleType=='30'}"> {{dictValueLabel(item.nodeHandleType,nodeTypeData)}}</span>
+          </div>
+        </template>
       </byTable>
     </div>
     <el-dialog :title="modalType == 'add' ? '新增' : '编辑'" v-model="dialogVisible" width="400" v-loading="loading">
@@ -56,6 +61,20 @@ let rules = ref({
   flowName: [{ required: true, message: "请输入流程名称", trigger: "blur" }],
 });
 const { proxy } = getCurrentInstance();
+const nodeTypeData = ref([
+  {
+    label: "常规",
+    value: "10",
+  },
+  {
+    label: "聚合",
+    value: "20",
+  },
+  {
+    label: "抄送",
+    value: "30",
+  },
+]);
 const selectConfig = computed(() => {
   return [
     {
@@ -89,6 +108,14 @@ const config = computed(() => {
     },
     {
       attrs: {
+        label: "节点类型",
+        prop: "nodeType",
+        slot: "nodeType",
+        width: 100,
+      },
+    },
+    {
+      attrs: {
         label: "流程状态",
         width: 100,
         prop: "status",
@@ -340,4 +367,10 @@ onMounted(() => {
 .tenant {
   padding: 20px;
 }
+.csNode {
+  background: #39c55a;
+  color: #fff;
+  border-radius: 2px;
+  padding: 4px;
+}
 </style>

+ 22 - 17
src/views/process/processApproval/index.vue

@@ -190,12 +190,16 @@
     <el-dialog :title="dialogTitle" width="400" v-model="dialogVisible" v-if="dialogVisible" :before-close="handleNextClose" :show-close="true"
                :close-on-click-modal="false" :close-on-press-escape="false">
       <el-form :model="flowForm">
-        <el-form-item label="处理人" v-if="nextHandleUser && nextHandleUser.length>0">
-          <el-select v-model="flowForm.handleUserId" placeholder="请选择" filterable style="width: 100%">
-            <el-option v-for="item in nextHandleUser" :label="item.nickName" :value="item.userId">
-            </el-option>
-          </el-select>
-        </el-form-item>
+
+        <div v-if="nextHandleUser && nextHandleUser.length>0">
+          <el-form-item v-for="node in nextHandleUser" :key="node.nodeId" :label="node.nodeName">
+            <el-select v-model="node.handleUserId" placeholder="请选择" filterable style="width: 100%">
+              <el-option v-for="item in node.userList" :label="item.nickName" :value="item.userId">
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </div>
+
         <el-form-item label="退回节点" v-if="flowDefinitionNodeList && flowDefinitionNodeList.length>0">
           <el-select v-model="flowForm.handleNodeId" placeholder="请选择" filterable style="width: 100%">
             <el-option v-for="item in flowDefinitionNodeList" :label="item.nodeName" :value="item.id">
@@ -303,11 +307,14 @@ const flowDefinitionNodeList = ref([]);
 const handleType = ref(null);
 const handleSelectUser = () => {
   if (nextHandleUser.value && nextHandleUser.value.length > 0) {
-    if (!flowForm.handleUserId) {
-      return ElMessage({
-        message: "请选择下一节点处理人!",
-        type: "info",
-      });
+    for (let i = 0; i < nextHandleUser.value.length; i++) {
+      const node = nextHandleUser.value[i];
+      if (!node.handleUserId) {
+        return ElMessage({
+          message: "请选择下一节点处理人!",
+          type: "info",
+        });
+      }
     }
   }
   if (flowDefinitionNodeList.value && flowDefinitionNodeList.value.length > 0) {
@@ -323,16 +330,13 @@ const handleSelectUser = () => {
 };
 
 const handleResult = (res) => {
-  if (
-    (res.userList == null && res.success) ||
-    (res.flowDefinitionNodeList == null && res.success)
-  ) {
+  if (res.success) {
     skipPage();
-  } else if (res.userList && res.userList.length > 0) {
+  } else if (res.selectUserList && res.selectUserList.length > 0) {
     flowDefinitionNodeList.value = [];
     dialogTitle.value = "下一处理人";
     dialogVisible.value = true;
-    nextHandleUser.value = res.userList;
+    nextHandleUser.value = res.selectUserList;
   } else if (
     res.flowDefinitionNodeList &&
     res.flowDefinitionNodeList.length > 0
@@ -404,6 +408,7 @@ const handleSubmit = async (_type) => {
                 version: route.query.version,
                 flowId: route.query.id,
                 skipSetData: true,
+                selectUserList: nextHandleUser.value || [],
               })
               .then(
                 (res) => {

+ 85 - 60
src/views/process/processConfig/handleBtn.vue

@@ -1,69 +1,94 @@
 <template>
-    <div class="handle-btn">
-        <div class="icon-box">
-            <div class="icon">
-                <i class="iconfont icon-icomx_banli"></i>
-            </div>
-            <div class="icon-text">办理</div>
-        </div>
-        <div class="title">{{title || '待配置'}}</div>
+  <div class="handle-btn">
+    <div class="icon-box">
+      <div class="icon cg" v-if="nodeHandleType=='10'">
+        <i class="iconfont icon-icomx_banli"></i>
+      </div>
+      <div class="icon jh" v-if="nodeHandleType=='20'">
+        <i class="iconfont icon-icomx_banli"></i>
+      </div>
+      <div class="icon cs" v-if="nodeHandleType=='30'">
+        <i class="iconfont icon-icomx_banli"></i>
+      </div>
+      <div class="icon-text">{{getNodeType()}}</div>
     </div>
+    <div class="title">{{title || '待配置'}}</div>
+  </div>
 </template>
 <script setup>
-    import { defineProps, inject, ref } from 'vue'
-    
-    let title = ref('')
-    let getNode = inject('getNode')
-    const node = getNode()
-    node.on('change:data', ({current}) => {
-        title.value = current.title
-    })
-    
+import { defineProps, inject, ref } from "vue";
 
+const title = ref("");
+const nodeHandleType = ref("10");
+const getNode = inject("getNode");
+const node = getNode();
+node.on("change:data", ({ current }) => {
+  nodeHandleType.value = current.nodeHandleType;
+  title.value = current.title;
+});
+const nodeTypeName = {
+  10: "常规",
+  20: "聚合",
+  30: "抄送",
+};
+const getNodeType = () => {
+  return nodeTypeName[nodeHandleType.value] + "节点";
+};
 </script>
 <style lang="scss">
-    .handle-btn{
-        height: 90px;
-        width: 150px;
-        background: #fff;
-        text-align: center;
-        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
-        border-radius: 10px 10px 10px 10px;
-        padding: 10px;
-        .title {
-            width: 100%;
-            height: 40px;
-            line-height: 40px;
-            padding: 0 20px;
-            text-align: left;
-            background: #eee;
-            border-radius: 10px;
-            margin-top: 10px;
-            //文字一行多余省略
-            white-space: nowrap;
-            overflow: hidden;
-            text-overflow: ellipsis;
-        }
-        .icon-box{
-            display: flex;
-            height: 20px;
-            line-height: 20px;
-            color: #333;
-            font-size: 14px;
-            .icon{
-                height: 20px;
-                width: 20px;
-                border-radius: 10px;
-                background: #FF9315;
-                color: #fff;
-                i{
-                    color: #fff;
-                    font-size: 12px;
-                }
-            }
-            .icon-text{
-                margin-left:10px;
-            }
-        }
+.handle-btn {
+  height: 90px;
+  width: 150px;
+  background: #fff;
+  text-align: center;
+  box-shadow: 0px 2px 10px 1px rgba(51, 51, 51, 0.1);
+  border-radius: 10px 10px 10px 10px;
+  padding: 10px;
+  .title {
+    width: 100%;
+    height: 40px;
+    line-height: 40px;
+    padding: 0 10px;
+    text-align: left;
+    background: #eee;
+    border-radius: 10px;
+    margin-top: 10px;
+    //文字一行多余省略
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: 15px;
+  }
+  .icon-box {
+    display: flex;
+    height: 20px;
+    line-height: 20px;
+    color: #333;
+    font-size: 14px;
+    .icon {
+      height: 20px;
+      width: 20px;
+      border-radius: 10px;
+      background: #ff9315;
+      color: #fff;
+      i {
+        color: #fff;
+        font-size: 12px;
+      }
     }
+    .icon-text {
+      margin-left: 10px;
+      font-size: 13px;
+    }
+    .cg {
+      background: #ff9315;
+    }
+    .jh {
+      background: #0084ff;
+    }
+    .cs {
+      background: #39c55a;
+    }
+  }
+}
 </style>

+ 379 - 166
src/views/process/processConfig/vueFlow.vue

@@ -1,64 +1,55 @@
-<template lang="">
-	<div class="vueFlow">
-		<div id="container"></div>
-		<div id="stencil"></div>
-		<div id="graph-container"></div>
-		<div id="minimap"></div>
-	</div>
-	<el-button @click="submitAll" type="primary" style="margin-top:15px">保存</el-button>
-	<el-dialog
-		title="节点信息配置"
-		v-model="dialogVisible"
-		width="800"
-		v-loading="loading"
-	>
-		<byForm
-			:formConfig="formType === 'handle-btn' ? formConfig : branchBtnConfig"
-			:formOption="formOption"
-			v-model="formData.data"
-			:rules="rules"
-			ref="byform"
-		>
-		</byForm>
-		<template #footer>
-			<el-button @click="dialogVisible = false" size="default"
-				>取 消</el-button
-			>
-			<el-button
-				type="danger"
-				@click="deleteFlowDefinitionNodeObj()"
-				size="default"
-				:loading="submitLoading"
-			>
-				删 除
-			</el-button>
-			<el-button
-				type="primary"
-				@click="submitForm('byform')"
-				size="default"
-				:loading="submitLoading"
-			>
-				确 定
-			</el-button>
-		</template>
-	</el-dialog>
-	<el-dialog
-		title="节点信息配置"
-		v-model="startModalType"
-		width="500"
-		v-loading="loading"
-	>
-		<div>
-			节点后执行方法
-			<el-input style="margin-top:10px" v-model="handlingMethod"></el-input>
-		</div>
-		<template #footer>
-  <el-button @click="startModalType = false" size="default">取 消</el-button>
-  <el-button type="primary" @click="startModalType = false" size="default" :loading="submitLoading">
-    确 定
-  </el-button>
-</template>
-	</el-dialog>
+<template>
+  <div>
+    <div class="vueFlow">
+      <div id="container"></div>
+      <div id="stencil"></div>
+      <div id="graph-container"></div>
+      <div id="minimap"></div>
+    </div>
+    <el-button @click="submitAll" type="primary" style="margin-top:15px">保存</el-button>
+
+    <el-dialog title="节点信息配置" v-model="dialogVisible" width="800" v-loading="loading">
+      <byForm :formConfig="formType === 'handle-btn' ? formConfig : branchBtnConfig" :formOption="formOption" v-model="formData.data" :rules="rules"
+              ref="byform">
+      </byForm>
+      <template #footer>
+        <el-button @click="dialogVisible = false" size="default">取 消</el-button>
+        <el-button type="danger" @click="deleteFlowDefinitionNodeObj()" size="default" :loading="submitLoading">
+          删 除
+        </el-button>
+        <el-button type="primary" @click="submitForm('byform')" size="default" :loading="submitLoading">
+          确 定
+        </el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="节点信息配置" v-model="startModalType" width="500">
+      <div v-loading="loading">
+        节点后执行方法
+        <el-input style="margin-top:10px" v-model="handlingMethod"></el-input>
+      </div>
+      <template #footer>
+        <el-button @click="startModalType = false" size="default">取 消</el-button>
+        <el-button type="primary" @click="startModalType = false" size="default" :loading="submitLoading">
+          确 定
+        </el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="线信息配置" v-model="lineDialog" width="800">
+      <byForm :formConfig="lineFormConfig" :formOption="formOption" v-model="formData.lineData" :rules="rules" ref="lineForm" v-loading="loading">
+      </byForm>
+      <template #footer>
+        <el-button @click="lineDialog = false" size="default">取 消</el-button>
+        <el-button type="danger" @click="deleteFlowLine()" size="default" :loading="submitLoading">
+          删 除
+        </el-button>
+        <el-button type="primary" @click="submitLineForm('byform')" size="default" :loading="submitLoading">
+          确 定
+        </el-button>
+      </template>
+    </el-dialog>
+  </div>
 </template>
 <script lang="ts" setup>
 import {
@@ -107,17 +98,99 @@ const dialogVisible = ref(false);
 const modalType = ref("add");
 const loading = ref(false);
 const submitLoading = ref(false);
-let formType = ref(1); //1办理 2分支
+const formType = ref(1); //1办理 2分支
 const formData = reactive({
   data: {
+    nodeName: "",
     userName: "",
     password: "",
+    id: "",
+    cell: null,
+    handleObjectId: "",
+    nodeButtonSet: null,
+    handleObjectType: "",
+    nodeHandleType: "",
+  },
+  lineData: {
+    lineUuid: "",
+    id: "",
+    cell: null,
+    jumpCondition: "",
+    sourceId: "",
+    targetId: "",
   },
 });
 const startModalType = ref(false);
+const lineDialog = ref(false);
 const handlingMethod = ref("");
 const byform = ref(null);
+const lineForm = ref(null);
 const flowDefinitionNodeObj = ref({});
+const flowDefinitionLineObj = ref({});
+const rankData = ref([
+  {
+    label: "员工",
+    value: 10,
+  },
+  {
+    label: "主管",
+    value: 20,
+  },
+  {
+    label: "经理",
+    value: 30,
+  },
+  {
+    label: "总监",
+    value: 40,
+  },
+]);
+const nodeTypeData = ref([
+  {
+    label: "常规",
+    value: "10",
+  },
+  {
+    label: "聚合",
+    value: "20",
+  },
+  {
+    label: "抄送",
+    value: "30",
+  },
+]);
+
+const btnData = ref([
+  {
+    label: "通过",
+    value: 1,
+    disabled: true,
+  },
+  {
+    label: "退回",
+    value: 8,
+  },
+  {
+    label: "驳回",
+    value: 2,
+  },
+  {
+    label: "加签",
+    value: 6,
+  },
+  {
+    label: "移交",
+    value: 7,
+  },
+]);
+
+const csBtn = ref([
+  {
+    label: "已读",
+    value: 1,
+    disabled: true,
+  },
+]);
 const rules = reactive({
   nodeName: [
     {
@@ -136,10 +209,35 @@ const rules = reactive({
   handleObjectId: [
     {
       required: true,
-      message: "办理人不能为空",
+      message: "请选择",
       trigger: "blur",
     },
   ],
+  jumpCondition: [
+    {
+      required: true,
+      message: "请输入条件表达式",
+      trigger: "blur",
+    },
+  ],
+  nodeHandleType: [
+    {
+      required: true,
+      message: "请选择",
+      trigger: "blur",
+    },
+  ],
+});
+const lineFormConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "jumpCondition",
+      label: "条件表达式",
+      required: true,
+      itemType: "text",
+    },
+  ];
 });
 const branchBtnConfig = computed(() => {
   return [
@@ -164,8 +262,8 @@ const formConfig = computed(() => {
     {
       type: "select",
       prop: "handleObjectType",
-      label: "办理",
-      placeholder: "请选择办理类型",
+      label: "办理类型",
+      placeholder: "请选择办理类型",
       required: true,
       itemWidth: 50,
       fn: (e) => {
@@ -174,7 +272,7 @@ const formConfig = computed(() => {
       //1用户 2部门负责人 3部门总监 4岗位 5角色
       data: [
         {
-          label: "指定用户",
+          label: "用户",
           value: 1,
         },
         // {
@@ -190,16 +288,16 @@ const formConfig = computed(() => {
         //   value: 4,
         // },
         {
-          label: "指定角色",
+          label: "角色",
           value: 5,
         },
         {
-          label: "动态用户",
-          value: 6,
+          label: "职级",
+          value: 8,
         },
         {
-          label: "部门主管",
-          value: 8,
+          label: "用户主群(需定制开发)",
+          value: 6,
         },
       ],
     },
@@ -212,78 +310,64 @@ const formConfig = computed(() => {
     // },
     {
       type: "select",
-      label: "",
+      label: "办理用户",
       itemWidth: 50,
       prop: "handleObjectId",
-      placeholder: "请选择办理",
+      placeholder: "请选择办理用户",
       data: selectHanleData.value,
       isShow:
-        formData.data.handleObjectType !== 5 &&
-        formData.data.handleObjectType !== 6 &&
-        formData.data.handleObjectType !== 8,
+        formData.data.handleObjectType &&
+        ![5, 6, 8].includes(formData.data.handleObjectType),
     },
     {
       type: "select",
-      label: "",
+      label: "办理角色",
       itemWidth: 50,
       prop: "handleObjectId",
       multiple: true,
-      placeholder: "请选择办理",
+      placeholder: "请选择办理角色",
       data: selectHanleData.value,
       isShow:
         formData.data.handleObjectType === 5 &&
         formData.data.handleObjectType !== 6,
     },
     {
-      type: "input",
-      prop: "handlingMethod",
-      label: "节点后置执行方法",
-      required: true,
-      itemType: "text",
+      type: "select",
+      label: "办理职级",
+      itemWidth: 50,
+      prop: "handleObjectId",
+      multiple: false,
+      placeholder: "请选择办理职级",
+      data: rankData.value,
+      isShow: formData.data.handleObjectType === 8,
     },
     {
-      type: "input",
-      prop: "jumpCondition",
-      label: "条件表达式",
-      required: true,
-      itemType: "text",
+      type: "select",
+      label: "节点类型",
+      itemWidth: 100,
+      prop: "nodeHandleType",
+      data: nodeTypeData.value,
     },
+    // {
+    //   type: "input",
+    //   prop: "handlingMethod",
+    //   label: "节点后置执行方法",
+    //   required: true,
+    //   itemType: "text",
+    // },
+    // {
+    //   type: "input",
+    //   prop: "jumpCondition",
+    //   label: "条件表达式",
+    //   required: true,
+    //   itemType: "text",
+    // },
     {
       type: "checkbox",
       prop: "nodeButtonSet",
       label: "节点按钮",
       //1通过 2驳回 3返回上一步 4退回到发起人
-      data: [
-        {
-          label: "通过",
-          value: 1,
-          disabled: true,
-        },
-        {
-          label: "退回",
-          value: 8,
-        },
-        // {
-        //   label: "退回",
-        //   value: 3,
-        // },
-        // {
-        //   label: "退回到发起人",
-        //   value: 4,
-        // },
-        {
-          label: "驳回",
-          value: 2,
-        },
-        {
-          label: "加签",
-          value: 6,
-        },
-        {
-          label: "移交",
-          value: 7,
-        },
-      ],
+      data: formData.data.nodeHandleType == "30" ? csBtn.value : btnData.value,
     },
     {
       type: "radio",
@@ -304,10 +388,10 @@ const formConfig = computed(() => {
 });
 const formOption = reactive({
   inline: true,
-  labelWidth: 130,
+  labelWidth: 100,
   itemWidth: 100,
 });
-let graph;
+let graph = null;
 const submitForm = () => {
   byform.value.handleSubmit((valid) => {
     //如果处理类型是角色, 则角色转,分割
@@ -321,10 +405,23 @@ const submitForm = () => {
     dialogVisible.value = false;
     formData.data.cell.setData({
       title: formData.data.nodeName,
+      nodeHandleType: formData.data.nodeHandleType,
     });
   });
 };
 
+const deleteFlowLine = (cell) => {
+  graph.removeNode(formData.lineData.id);
+  lineDialog.value = false;
+};
+
+const submitLineForm = () => {
+  lineForm.value.handleSubmit((valid) => {
+    flowDefinitionLineObj.value[formData.lineData.id] = formData.lineData;
+    lineDialog.value = false;
+  });
+};
+
 const submitFormData = {
   flowInfoId: null,
   titleTemplate: null,
@@ -332,6 +429,7 @@ const submitFormData = {
   nodeObject: "",
   lineObject: "",
   flowDefinitionNodeList: [],
+  flowDefinitionLineList: [],
 };
 const dataRollback = () => {
   for (const key in flowDefinitionNodeObj.value) {
@@ -339,11 +437,18 @@ const dataRollback = () => {
       flowDefinitionNodeObj.value[key].handleObjectType &&
       flowDefinitionNodeObj.value[key].handleObjectType === 5
     ) {
-      flowDefinitionNodeObj.value[key].handleObjectId =
-        flowDefinitionNodeObj.value[key].handleObjectId.split(",");
+      if (flowDefinitionNodeObj.value[key].handleObjectId) {
+        flowDefinitionNodeObj.value[key].handleObjectId =
+          flowDefinitionNodeObj.value[key].handleObjectId.split(",");
+      }
     }
   }
 };
+const allNodeData = ref([]);
+// 抄送节点
+const csNodeList = ref([]);
+// 线数据
+const lineNodeList = ref([]);
 const submitAll = () => {
   if (proxy.title == "") {
     ElMessage({
@@ -352,26 +457,35 @@ const submitAll = () => {
     });
     return;
   }
+  // 清空数据
+  csNodeList.value = [];
+  lineNodeList.value = [];
   // 如果选择类型是角色,则角色数据转成 ','分割
   for (const key in flowDefinitionNodeObj.value) {
     if (
       flowDefinitionNodeObj.value[key].handleObjectType &&
       flowDefinitionNodeObj.value[key].handleObjectType === 5
     ) {
-      flowDefinitionNodeObj.value[key].handleObjectId =
-        flowDefinitionNodeObj.value[key].handleObjectId.join(",");
+      if (flowDefinitionNodeObj.value[key].handleObjectId) {
+        flowDefinitionNodeObj.value[key].handleObjectId =
+          flowDefinitionNodeObj.value[key].handleObjectId.join(",");
+      }
     }
   }
-
   submitFormData.titleTemplate = proxy.title;
-  const nodeList = graph.toJSON().cells;
-  submitFormData.nodeObject = JSON.stringify(nodeList);
+  allNodeData.value = graph.toJSON().cells;
+  submitFormData.nodeObject = JSON.stringify(allNodeData.value);
   submitFormData.lineObject = JSON.stringify(flowDefinitionNodeObj.value);
-
-  // console.log(nodeList);
-  const isStart = false;
-  for (let i = 0; i < nodeList.length; i++) {
-    const element = nodeList[i];
+  for (let i = 0; i < allNodeData.value.length; i++) {
+    const element = allNodeData.value[i];
+    // 抄送节点
+    if (
+      element.shape == "handle-btn" &&
+      element.data &&
+      element.data.nodeHandleType == "30"
+    ) {
+      csNodeList.value.push(element);
+    }
     //是办理节点
     if (
       element.shape != "start-btn" &&
@@ -408,6 +522,18 @@ const submitAll = () => {
     }
     //说明是线
     if (element.shape == "edge") {
+      lineNodeList.value.push(element);
+      // 线数据对象
+      if (!flowDefinitionLineObj.value[element.id]) {
+        flowDefinitionLineObj.value[element.id] = {
+          lineUuid: element.id,
+          id: element.id,
+          jumpCondition: "",
+          sourceId: element.source.cell,
+          targetId: element.target.cell,
+        };
+      }
+
       if (!flowDefinitionNodeObj.value[element.target.cell]) {
         ElMessage({
           message: "有节点未配置,请检查节点",
@@ -422,6 +548,24 @@ const submitAll = () => {
       submitFormData.flowDefinitionNodeList = [];
     }
   }
+  if (csNodeList.value && csNodeList.value.length > 0) {
+    for (let i = 0; i < csNodeList.value.length; i++) {
+      const node = csNodeList.value[i];
+      for (let j = 0; j < lineNodeList.value.length; j++) {
+        const line = lineNodeList.value[j];
+        // 如果线的开始节点是抄送节点
+        if (line.source.cell == node.id) {
+          ElMessage({
+            message: "抄送节点不可做为起始节点",
+            type: "warning",
+          });
+          dataRollback();
+          return;
+        }
+      }
+    }
+  }
+
   addVersion();
 };
 
@@ -439,6 +583,7 @@ const addVersion = () => {
   const idObg = {};
   for (let i = 0; i < submitFormData.flowDefinitionNodeList.length; i++) {
     const element = submitFormData.flowDefinitionNodeList[i];
+    element.oldNodeId = element.id;
     if (element.parentId == null && element.nodeName == "结束") {
       ElMessage({
         message: "有结束节点未连线,请配置",
@@ -470,8 +615,51 @@ const addVersion = () => {
       element.nodeButtonSet = element.nodeButtonSet.join(",");
     }
   }
+  // 线数据
+  for (let i = 0; i < allNodeData.value.length; i++) {
+    const node = allNodeData.value[i];
+    if (node.shape == "edge") {
+      let lineData = flowDefinitionLineObj.value[node.id];
+      // 找源节点
+      let sourceCell = submitFormData.flowDefinitionNodeList.find(
+        (x) => x.oldNodeId == lineData.sourceId
+      );
+      let sourceId = "";
+      if (sourceCell) {
+        sourceId = sourceCell.id;
+      } else {
+        ElMessage({
+          message: "未找到源节点",
+          type: "warning",
+        });
+        dataRollback();
+        return;
+      }
+      // 找目标节点
+      let targetCell = submitFormData.flowDefinitionNodeList.find(
+        (x) => x.oldNodeId == lineData.targetId
+      );
+      let targetId = "";
+      if (targetCell) {
+        targetId = targetCell.id;
+      } else {
+        ElMessage({
+          message: "未找到目标节点",
+          type: "warning",
+        });
+        dataRollback();
+        return;
+      }
+      submitFormData.flowDefinitionLineList.push({
+        lineUuid: lineData.id,
+        jumpCondition: lineData.jumpCondition,
+        sourceId,
+        targetId,
+      });
+    }
+  }
 
-  proxy.post("/flowDefinition/addVersion", submitFormData).then((res) => {
+  proxy.post("/flowDefinition/addVersion", submitFormData).then(() => {
     ElMessage({
       message: "保存成功",
       type: "success",
@@ -725,21 +913,38 @@ const antvInit = (data) => {
   });
   // #endregion
   graph.on("cell:click", ({ e, x, y, cell, view }) => {
-    // console.log(flowDefinitionNodeObj.value);
-    // console.log(cell);
     if (cell.shape === "start-btn") {
       startModalType.value = true;
       return;
     }
-    if (cell.shape === "end-btn" || cell.shape === "edge") {
+    if (cell.shape === "end-btn") {
       ElMessageBox.confirm("是否删除", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning",
-      }).then(() => {
-        graph.removeNode(cell.id);
-        // delete flowDefinitionNodeObj.value[id]
-      });
+      })
+        .then(() => {
+          graph.removeNode(cell.id);
+        })
+        .catch((err) => {
+          console.log("取消");
+        });
+      return;
+    }
+    if (cell.shape === "edge") {
+      lineDialog.value = true;
+      if (flowDefinitionLineObj.value[cell.id]) {
+        formData.lineData = flowDefinitionLineObj.value[cell.id];
+      } else {
+        formData.lineData = {
+          lineUuid: cell.id,
+          id: cell.id,
+          cell: cell,
+          jumpCondition: "",
+          sourceId: cell.store.data.source.cell,
+          targetId: cell.store.data.target.cell,
+        };
+      }
       return;
     }
     formType.value = cell.shape;
@@ -757,6 +962,7 @@ const antvInit = (data) => {
         id: cell.id,
         cell: cell,
         nodeButtonSet: [1],
+        nodeHandleType: "10",
       };
     }
 
@@ -923,17 +1129,17 @@ const antvInit = (data) => {
       },
     },
   });
-  const r3 = graph.createNode({
-    shape: "branch-btn",
-    label: "分支",
-    zIndex: 100,
-    attrs: {
-      body: {
-        rx: 40,
-        ry: 46,
-      },
-    },
-  });
+  // const r3 = graph.createNode({
+  //   shape: "branch-btn",
+  //   label: "分支",
+  //   zIndex: 100,
+  //   attrs: {
+  //     body: {
+  //       rx: 40,
+  //       ry: 46,
+  //     },
+  //   },
+  // });
   const r4 = graph.createNode({
     shape: "end-btn",
     label: "结束",
@@ -945,7 +1151,7 @@ const antvInit = (data) => {
       },
     },
   });
-  stencil.load([r2, r3, r4], "group1");
+  stencil.load([r2, r4], "group1");
   // const startNode = graph.addNode({
   // 	shape: 'custom-rect',
   // 	label: '开始',
@@ -983,24 +1189,32 @@ const getFlowInfo = () => {
           }
         }
       }
+
+      if (res.flowDefinitionLineList && res.flowDefinitionLineList.length) {
+        for (let i = 0; i < res.flowDefinitionLineList.length; i++) {
+          const lineNode = res.flowDefinitionLineList[i];
+          flowDefinitionLineObj.value[lineNode.lineUuid] = {
+            lineUuid: lineNode.lineUuid,
+            id: lineNode.lineUuid,
+            jumpCondition: lineNode.jumpCondition || "",
+          };
+        }
+      }
+
       if (res.nodeObject) {
         antvInit(JSON.parse(res.nodeObject));
       } else {
         antvInit();
       }
       for (const key in flowDefinitionNodeObj.value) {
-        //延迟等待dom渲染完成
         setTimeout(() => {
-          if (
-            flowDefinitionNodeObj.value[key].nodeName != "结束" &&
-            flowDefinitionNodeObj.value[key].cell != "开始"
-          ) {
-            let htmlNode = document.querySelector(
-              "g[data-cell-id='" + key + "']"
-            );
-            //获取htmlNode节点下的title,修改title的内容
-            htmlNode.getElementsByClassName("title")[0].innerHTML =
-              flowDefinitionNodeObj.value[key].nodeName;
+          let cell = graph.getCellById(key);
+          if (cell) {
+            cell.setData({
+              random: proxy.random(),
+              title: flowDefinitionNodeObj.value[key].nodeName,
+              nodeHandleType: flowDefinitionNodeObj.value[key].nodeHandleType,
+            });
           }
         }, 2000);
       }
@@ -1026,7 +1240,6 @@ onMounted(() => {
     // setTimeout(() => {
     // 	for (let i = 0; i < dataJson.flowDefinitionNodeList.length; i++) {
     // 		const element = dataJson.flowDefinitionNodeList[i];
-    // 		console.log(element)
     // 		if(!element.cell) {
     // 			continue
     // 		}
@@ -1104,6 +1317,6 @@ onMounted(() => {
   }
 }
 #stencil .x6-widget-stencil-content .x6-widget-stencil-group-content .x6-graph {
-  height: 900px !important;
+  // height: 900px !important;
 }
 </style>

+ 14 - 0
src/views/purchaseManage/supplier/supplier/index.vue

@@ -5,6 +5,11 @@
                :selectConfig="selectConfig" :table-events="{
           select: select,
         }" :action-list="[
+           {
+                text: '导出Excel',
+                action: () => exportExcel(),
+                disabled: false,
+              },
           {
             text: '添加供应商',
             action: () => openModal('add'),
@@ -801,6 +806,15 @@ const getDict = () => {
 getDict();
 getCityData("0");
 getList();
+
+const exportExcel = () => {
+  proxy.msgTip("正在导出,请稍后", 2);
+  proxy
+    .postTwo("/supplierInfo/excelExport", sourceList.value.pagination)
+    .then((res) => {
+      proxy.downloadFile(res, "供应商数据.xlsx");
+    });
+};
 </script>
 
 <style lang="scss" scoped>