Ver Fonte

整体结构变更 新增方法数据错乱问题修复

pixel há 4 anos atrás
pai
commit
a6acc90a6c

+ 2 - 1
server/initialize/gorm.go

@@ -40,7 +40,8 @@ func MysqlTables(db *gorm.DB) {
 		model.WorkflowProcess{},
 		model.WorkflowNode{},
 		model.WorkflowEdge{},
-		model.WorkflowPoint{},
+		model.WorkflowStartPoint{},
+		model.WorkflowEndPoint{},
 	)
 	if err != nil {
 		global.GVA_LOG.Error("register table failed", zap.Any("err", err))

+ 32 - 25
server/model/wf_process.go

@@ -1,6 +1,7 @@
 package model
 
 import (
+	"gin-vue-admin/global"
 	"gorm.io/gorm"
 	"time"
 )
@@ -17,7 +18,7 @@ type WorkflowProcess struct {
 	HideIcon    bool           `json:"hideIcon" gorm:"comment:是否隐藏图标"`
 	Description string         `json:"description" gorm:"comment:详细介绍"`
 	Nodes       []WorkflowNode `json:"nodes"` // 流程节点数据
-
+	Edges       []WorkflowEdge `json:"edges"` // 流程链接数据
 }
 
 type WorkflowNode struct {
@@ -41,37 +42,43 @@ type WorkflowNode struct {
 	Cycle             string         `json:"cycle" gorm:"comment:循环时间"`
 	Duration          string         `json:"duration" gorm:"comment:持续时间"`
 	HideIcon          bool           `json:"hideIcon" gorm:"comment:是否隐藏图标"`
-	Edges             []WorkflowEdge `json:"edges"` // 流程链接数据
 }
 
 type WorkflowEdge struct {
 	ID                  string `json:"id" form:"id" gorm:"comment:唯一标识;primaryKey;unique;not null"`
 	CreatedAt           time.Time
 	UpdatedAt           time.Time
-	DeletedAt           gorm.DeletedAt `gorm:"index"`
-	WorkflowNodeID      string         `json:"-" gorm:"comment:节点标识"`
-	Clazz               string         `json:"clazz" gorm:"comment:类型(线)"`
-	Source              string         `json:"source" gorm:"comment:起点节点"`
-	Target              string         `json:"target" gorm:"comment:目标节点"`
-	SourceAnchor        int            `json:"sourceAnchor" gorm:"comment:起点"`
-	TargetAnchor        int            `json:"targetAnchor" gorm:"comment:目标点"`
-	Shape               string         `json:"shape" gorm:"comment:形状"`
-	StartPoint          WorkflowPoint  `json:"startPoint"` // 起点信息
-	EndPoint            WorkflowPoint  `json:"endPoint"`   // 终点信息
-	Label               string         `json:"label" gorm:"comment:标题"`
-	HideIcon            bool           `json:"hideIcon" gorm:"comment:隐藏图标"`
-	ConditionExpression string         `json:"conditionExpression" gorm:"comment:条件标识"`
-	Seq                 string         `json:"seq" gorm:"comment:序号"`
-	Reverse             bool           `json:"reverse" gorm:"comment:是否反向"`
+	DeletedAt           gorm.DeletedAt     `gorm:"index"`
+	WorkflowProcessID   string             `json:"-" gorm:"comment:流程标识"`
+	Clazz               string             `json:"clazz" gorm:"comment:类型(线)"`
+	Source              string             `json:"source" gorm:"comment:起点节点"`
+	Target              string             `json:"target" gorm:"comment:目标节点"`
+	SourceAnchor        int                `json:"sourceAnchor" gorm:"comment:起点"`
+	TargetAnchor        int                `json:"targetAnchor" gorm:"comment:目标点"`
+	Shape               string             `json:"shape" gorm:"comment:形状"`
+	StartPoint          WorkflowStartPoint `json:"startPoint"` // 起点信息
+	EndPoint            WorkflowEndPoint   `json:"endPoint"`   // 终点信息
+	Label               string             `json:"label" gorm:"comment:标题"`
+	HideIcon            bool               `json:"hideIcon" gorm:"comment:隐藏图标"`
+	ConditionExpression string             `json:"conditionExpression" gorm:"comment:条件标识"`
+	Seq                 string             `json:"seq" gorm:"comment:序号"`
+	Reverse             bool               `json:"reverse" gorm:"comment:是否反向"`
+}
+
+type WorkflowStartPoint struct {
+	WorkflowEdgeID string
+	WorkflowPoint
+}
+
+type WorkflowEndPoint struct {
+	WorkflowEdgeID string
+	WorkflowPoint
 }
 
+//
 type WorkflowPoint struct {
-	ID             string `json:"-" gorm:"comment:唯一标识;primaryKey;unique;not null"`
-	CreatedAt      time.Time
-	UpdatedAt      time.Time
-	DeletedAt      gorm.DeletedAt `gorm:"index"`
-	WorkflowEdgeID string         `json:"-"`
-	X              float64        `json:"x"`
-	Y              float64        `json:"y"`
-	Index          int            `json:"index"`
+	global.GVA_MODEL
+	X     float64 `json:"x"`
+	Y     float64 `json:"y"`
+	Index int     `json:"index"`
 }

+ 1 - 1
server/service/wk_process.go

@@ -58,7 +58,7 @@ func UpdateWorkflowProcess(workflowProcess *model.WorkflowProcess) (err error) {
 // @return    WorkflowProcess        WorkflowProcess
 
 func GetWorkflowProcess(id string) (err error, workflowProcess model.WorkflowProcess) {
-	err = global.GVA_DB.Preload("Nodes").Preload("Nodes.Edges").Where("id = ?", id).First(&workflowProcess).Error
+	err = global.GVA_DB.Preload("Nodes").Preload("Edges").Where("id = ?", id).First(&workflowProcess).Error
 	return
 }
 

+ 1 - 1
web/src/components/gva-wfd/components/DetailPanel/ProcessDetail.vue

@@ -5,7 +5,7 @@
             <div class="panelRow">
                 <div>{{i18n['process.id']}}:</div>
                 <el-input style="width:90%; font-size:12px"
-                          :disabled="readOnly"
+                          :disabled="readOnly || this.$route.query.type!='create'"
                           placeholder="必填(唯一标识)"
                           :value="model.id"
                           @input="(value) => {onChange('id', value)}" />

+ 8 - 4
web/src/components/gva-wfd/components/Wfd.vue

@@ -8,7 +8,7 @@
                    v-if="!isView"
                    :height="height"
                    :model="selectedModel"
-                   :readOnly="mode !== 'edit'"
+                   :readOnly="$route.query.type == 'view'"
                    :users="users"
                    :authorities="authorities"
                    :groups="groups"
@@ -84,9 +84,9 @@
         type: Array,
         default: () => ([])
       },
-      processModel:{
+      propProcessModel:{
          type: Object,
-        default: () => ({
+          default: () => ({
           id: '',
           name: '',
           category: '',
@@ -99,6 +99,7 @@
     },
     data() {
       return {
+        processModel:{},
         resizeFunc: ()=>{},
         selectedModel: {},
         graph:null,
@@ -245,7 +246,10 @@
         this.graph.fitView(5)
       }
       this.initEvents();
-    }
+    },
+    created() {
+      this.processModel = this.propProcessModel
+    },
   };
 </script>
 <style lang="scss" scoped>

+ 218 - 44
web/src/view/workflow/workflowCreate/workflowCreate.vue

@@ -2,21 +2,36 @@
   <div>
     <el-button
       size="small"
-      style="float:right;margin-top:6px;margin-right:6px;"
+      style="float: right; margin-top: 6px; margin-right: 6px"
       @click="saveXML"
-    >导出XML</el-button>
+      >导出XML</el-button
+    >
     <el-button
       size="small"
-      style="float:right;margin-top:6px;margin-right:6px;"
+      style="float: right; margin-top: 6px; margin-right: 6px"
       @click="saveImg"
-    >导出图片</el-button>
+      >导出图片</el-button
+    >
     <el-popover placement="bottom" width="160" v-model="visible">
       <p>确认流程无误并保存吗</p>
       <div style="text-align: right; margin: 0">
-        <el-button size="mini" type="text" @click="visible = false">取消</el-button>
-        <el-button type="primary" size="mini" @click="save">确定</el-button>
+        <el-button size="mini" type="text" @click="visible = false"
+          >取消</el-button
+        >
+        <el-button
+          type="primary"
+          size="mini"
+          @click="save"
+          :disabled="$route.query.type == 'view'"
+          >确定</el-button
+        >
       </div>
-      <el-button size="small" slot="reference" style="float:right;margin-top:6px;margin-right:6px;">保存流程</el-button>
+      <el-button
+        size="small"
+        slot="reference"
+        style="float: right; margin-top: 6px; margin-right: 6px"
+        >保存流程</el-button
+      >
     </el-popover>
 
     <gva-wfd
@@ -29,7 +44,7 @@
       :groups="groups"
       :categorys="categorys"
       :lang="lang"
-      :processModel="processModel"
+      :propProcessModel="processModel"
     />
   </div>
 </template>
@@ -41,7 +56,6 @@ import {
 import gvaWfd from "@/components/gva-wfd";
 import { getUserList } from "@/api/user";
 import { getAuthorityList } from "@/api/authority";
-import edge from '../../../components/gva-wfd/shape/edge';
 export default {
   name: "Workflow",
   components: {
@@ -52,7 +66,179 @@ export default {
       visible: false,
       lang: "zh",
       done:false,
-      demoData: {},
+      demoData: {
+        // nodes: [
+        //   {
+        //     clazz: "start",
+        //     label: "发起请假",
+        //     type: "start-node",
+        //     shape: "start-node",
+        //     x: 110,
+        //     y: 195,
+        //     id: "start1603681292875",
+        //     style: {}
+        //   },
+        //   {
+        //     clazz: "parallelGateway",
+        //     label: "会签",
+        //     type: "parallel-gateway-node",
+        //     shape: "parallel-gateway-node",
+        //     x: 228,
+        //     y: 195,
+        //     id: "parallelGateway1603681296419",
+        //     style: {}
+        //   },
+        //   {
+        //     clazz: "userTask",
+        //     label: "审批人1",
+        //     type: "user-task-node",
+        //     shape: "user-task-node",
+        //     x: 372,
+        //     y: 84,
+        //     id: "userTask1603681299962",
+        //     style: {},
+        //     assignValue: 1,
+        //     assignType: "user"
+        //   },
+        //   {
+        //     clazz: "userTask",
+        //     label: "审批人2",
+        //     type: "user-task-node",
+        //     shape: "user-task-node",
+        //     x: 370,
+        //     y: 321,
+        //     id: "userTask1603681302372",
+        //     style: {},
+        //     assignValue: 2,
+        //     assignType: "user"
+        //   },
+        //   {
+        //     clazz: "parallelGateway",
+        //     label: "会签结果检测",
+        //     type: "parallel-gateway-node",
+        //     shape: "parallel-gateway-node",
+        //     x: 519,
+        //     y: 195,
+        //     id: "parallelGateway1603681338222",
+        //     style: {}
+        //   },
+        //   {
+        //     clazz: "end",
+        //     label: "请假失败",
+        //     type: "end-node",
+        //     shape: "end-node",
+        //     x: 704,
+        //     y: 317,
+        //     id: "end1603681358043",
+        //     style: {}
+        //   },
+        //   {
+        //     clazz: "end",
+        //     label: "请假成功",
+        //     type: "end-node",
+        //     shape: "end-node",
+        //     x: 706.5,
+        //     y: 55.5,
+        //     id: "end1603681360882",
+        //     style: {}
+        //   }
+        // ],
+        // edges: [
+        //   {
+        //     id: "flow1603681320738",
+        //     clazz: "flow",
+        //     source: "parallelGateway1603681296419",
+        //     target: "userTask1603681299962",
+        //     sourceAnchor: 0,
+        //     targetAnchor: 3,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 228, y: 169, index: 0 },
+        //     endPoint: { x: 321.5, y: 84, index: 3 }
+        //   },
+        //   {
+        //     id: "flow1603681321969",
+        //     clazz: "flow",
+        //     source: "parallelGateway1603681296419",
+        //     target: "userTask1603681302372",
+        //     sourceAnchor: 2,
+        //     targetAnchor: 3,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 228, y: 221, index: 2 },
+        //     endPoint: { x: 319.5, y: 321, index: 3 }
+        //   },
+        //   {
+        //     id: "flow1603681323274",
+        //     clazz: "flow",
+        //     source: "start1603681292875",
+        //     target: "parallelGateway1603681296419",
+        //     sourceAnchor: 1,
+        //     targetAnchor: 3,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 138, y: 195, index: 1 },
+        //     endPoint: { x: 202, y: 195, index: 3 },
+        //     label: "发起",
+        //     conditionExpression: "complete"
+        //   },
+        //   {
+        //     id: "flow1603681341777",
+        //     clazz: "flow",
+        //     source: "userTask1603681299962",
+        //     target: "parallelGateway1603681338222",
+        //     sourceAnchor: 1,
+        //     targetAnchor: 3,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 422.5, y: 84, index: 1 },
+        //     endPoint: { x: 493, y: 195, index: 3 }
+        //   },
+        //   {
+        //     id: "flow1603681343425",
+        //     clazz: "flow",
+        //     source: "userTask1603681302372",
+        //     target: "parallelGateway1603681338222",
+        //     sourceAnchor: 1,
+        //     targetAnchor: 3,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 420.5, y: 321, index: 1 },
+        //     endPoint: { x: 493, y: 195, index: 3 }
+        //   },
+        //   {
+        //     id: "flow1603681362913",
+        //     clazz: "flow",
+        //     source: "parallelGateway1603681338222",
+        //     target: "end1603681360882",
+        //     sourceAnchor: 0,
+        //     targetAnchor: 2,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 519, y: 169, index: 0 },
+        //     endPoint: { x: 678.5, y: 55.5, index: 2 },
+        //     conditionExpression: "complete",
+        //     label: "所有人同意"
+        //   },
+        //   {
+        //     id: "flow1603681392729",
+        //     clazz: "flow",
+        //     source: "parallelGateway1603681338222",
+        //     target: "end1603681358043",
+        //     sourceAnchor: 2,
+        //     targetAnchor: 2,
+        //     shape: "flow-polyline-round",
+        //     style: {},
+        //     startPoint: { x: 519, y: 221, index: 2 },
+        //     endPoint: { x: 676, y: 317, index: 2 },
+        //     conditionExpression: "reject",
+        //     label: "任何一人拒绝"
+        //   }
+        // ],
+      },
+      wkType:"create",
+      users: [],
+      authorities: [],
       processModel:{
           id: '',
           name: '',
@@ -62,8 +248,6 @@ export default {
           signalDefs: [],
           messageDefs: [],
         },
-      users: [],
-      authorities: [],
       groups: [
         { id: "1", name: "组1" },
         { id: "2", name: "组2" },
@@ -81,34 +265,27 @@ export default {
     async save() {
       this.visible = false;
       const obj = this.$refs["wfd"].graph.save()
-      const processModel = this.processModel
-      const nodeMap={}
-
-      obj.edges.map(item=>{
-        if(nodeMap[item.source]){
-          nodeMap[item.source].push(item)
-        }else{
-          nodeMap[item.source] = [item]
-        }
-      })
-      obj.nodes.map(item=>{
-        item.edges = nodeMap[item.id]
-      })
+      const processModel = this.$refs["wfd"].processModel
+      processModel.edges = obj.edges
       processModel.nodes = obj.nodes
       if(!processModel.id){
         this.$message({
-         type:"error",
-         message:"流程ID为必填项(点击空白处录入流程基本信息)"
-       })
-       return
+          type:"error",
+          message:"流程id必填,点击空白处填写流程基本信息"
+        })
+        return
       }
-     const res = await createWorkflowProcess(processModel)
-     if(res.code == 0){
-       this.$message({
-         type:"success",
-         message:"创建成功"
-       })
-     }
+      // if(this.$route.query.type == 'edit'){
+      //   // 等待调用编辑功能
+      // }else{
+        const res = await createWorkflowProcess(processModel)
+        if(res.success){
+          this.$message({
+            type:"success",
+            message:"创建成功"
+          })
+        }
+      // }
     },
     saveXML() {
       console.log(this.$refs["wfd"].graph.saveXML());
@@ -137,19 +314,16 @@ export default {
       const res = await findWorkflowProcess({ id: this.$route.query.id });
       this.disabled = this.$route.query.type == "view"
       if(res.code == 0){
-        const nodes = []
-        const edges = []
-        res.data.reworkflowProcess.nodes.map(item=>{
-          edges.push(...item.edges)
-          delete item.edges
-          nodes.push(item)
-        })
+        this.demoData.nodes = res.data.reworkflowProcess.nodes
         delete res.data.reworkflowProcess.nodes
-        this.demoData = {edges,nodes}
+        this.demoData.edges = res.data.reworkflowProcess.edges
+        delete res.data.reworkflowProcess.edges
         this.processModel = res.data.reworkflowProcess
       }
+      this.wkType = this.$route.query.type
     }
         this.done = true
+
   }
 };
 </script>

+ 85 - 45
web/src/view/workflow/workflowProcess/workflowProcess.vue

@@ -4,21 +4,34 @@
       <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
         <el-form-item label="流程名称">
           <el-input placeholder="搜索条件" v-model="searchInfo.name"></el-input>
-        </el-form-item>        
+        </el-form-item>
         <el-form-item label="流程标题">
-          <el-input placeholder="搜索条件" v-model="searchInfo.label"></el-input>
-        </el-form-item>        
+          <el-input
+            placeholder="搜索条件"
+            v-model="searchInfo.label"
+          ></el-input>
+        </el-form-item>
         <el-form-item>
           <el-button @click="onSubmit" type="primary">查询</el-button>
         </el-form-item>
         <el-form-item>
           <el-popover placement="top" v-model="deleteVisible" width="160">
             <p>确定要删除吗?</p>
-              <div style="text-align: right; margin: 0">
-                <el-button @click="deleteVisible = false" size="mini" type="text">取消</el-button>
-                <el-button @click="onDelete" size="mini" type="primary">确定</el-button>
-              </div>
-            <el-button icon="el-icon-delete" size="mini" slot="reference" type="danger">批量删除</el-button>
+            <div style="text-align: right; margin: 0">
+              <el-button @click="deleteVisible = false" size="mini" type="text"
+                >取消</el-button
+              >
+              <el-button @click="onDelete" size="mini" type="primary"
+                >确定</el-button
+              >
+            </div>
+            <el-button
+              icon="el-icon-delete"
+              size="mini"
+              slot="reference"
+              type="danger"
+              >批量删除</el-button
+            >
           </el-popover>
         </el-form-item>
       </el-form>
@@ -32,32 +45,73 @@
       style="width: 100%"
       tooltip-effect="dark"
     >
-    <el-table-column type="selection" width="55"></el-table-column>
-    
-    <el-table-column label="流程名称" prop="name" width="120"></el-table-column> 
-    
-    <el-table-column label="分类" prop="category" width="120"></el-table-column> 
-    
-    <el-table-column label="类型" prop="clazz" width="120"></el-table-column> 
-    
-    <el-table-column label="流程标题" prop="label" width="120"></el-table-column> 
-    
-    <el-table-column label="是否隐藏图标" prop="hideIcon" width="120">
-         <template slot-scope="scope">{{scope.row.hideIcon|formatBoolean}}</template>
-    </el-table-column>
-    
-    <el-table-column label="详细介绍" prop="description" width="120"></el-table-column> 
-    
+      <el-table-column type="selection" width="55"></el-table-column>
+  <el-table-column label="日期" width="180">
+        <template slot-scope="scope">{{scope.row.CreatedAt|formatDate}}</template>
+      </el-table-column>
+      <el-table-column
+        label="流程名称"
+        prop="name"
+        width="120"
+      ></el-table-column>
+
+      <el-table-column
+        label="分类"
+        prop="category"
+        width="120"
+      ></el-table-column>
+
+      <el-table-column label="类型" prop="clazz" width="120"></el-table-column>
+
+      <el-table-column
+        label="流程标题"
+        prop="label"
+        width="120"
+      ></el-table-column>
+
+      <el-table-column label="是否隐藏图标" prop="hideIcon" width="120">
+        <template slot-scope="scope">{{
+          scope.row.hideIcon | formatBoolean
+        }}</template>
+      </el-table-column>
+
+      <el-table-column
+        label="详细介绍"
+        prop="description"
+        width="120"
+      ></el-table-column>
+
       <el-table-column label="按钮组">
         <template slot-scope="scope">
-          <el-button @click="updateWorkflowProcess(scope.row)" size="small" type="primary">变更</el-button>
+          <el-button
+            @click="updateWorkflowProcess(scope.row)"
+            size="small"
+            type="primary"
+            >变更</el-button
+          >
           <el-popover placement="top" width="160" v-model="scope.row.visible">
             <p>确定要删除吗?</p>
             <div style="text-align: right; margin: 0">
-              <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
-              <el-button type="primary" size="mini" @click="deleteWorkflowProcess(scope.row)">确定</el-button>
+              <el-button
+                size="mini"
+                type="text"
+                @click="scope.row.visible = false"
+                >取消</el-button
+              >
+              <el-button
+                type="primary"
+                size="mini"
+                @click="deleteWorkflowProcess(scope.row)"
+                >确定</el-button
+              >
             </div>
-            <el-button type="danger" icon="el-icon-delete" size="mini" slot="reference">删除</el-button>
+            <el-button
+              type="danger"
+              icon="el-icon-delete"
+              size="mini"
+              slot="reference"
+              >删除</el-button
+            >
           </el-popover>
         </template>
       </el-table-column>
@@ -67,7 +121,7 @@
       :current-page="page"
       :page-size="pageSize"
       :page-sizes="[10, 30, 50, 100]"
-      :style="{float:'right',padding:'20px'}"
+      :style="{ float: 'right', padding: '20px' }"
       :total="total"
       @current-change="handleCurrentChange"
       @size-change="handleSizeChange"
@@ -82,7 +136,7 @@ import {
     deleteWorkflowProcessByIds,
     getWorkflowProcessList
 } from "@/api/workflowProcess";  //  此处请自行替换地址
-import { formatTimeToStr } from "@/utils/data";
+import { formatTimeToStr } from "@/utils/date";
 import infoList from "@/components/mixins/infoList";
 
 export default {
@@ -94,9 +148,7 @@ export default {
       dialogFormVisible: false,
       visible: false,
       deleteVisible: false,
-      multipleSelection: [],formData: {
-        name:null,category:null,clazz:null,label:null,hideIcon:null,description:null,
-      }
+      multipleSelection: [],
     };
   },
   filters: {
@@ -151,18 +203,6 @@ export default {
         type:'edit'
       }})
     },
-    closeDialog() {
-      this.dialogFormVisible = false;
-      this.formData = {
-        
-          name:null,
-          category:null,
-          clazz:null,
-          label:null,
-          hideIcon:null,
-          description:null,
-      };
-    },
     async deleteWorkflowProcess(row) {
       this.visible = false;
       const res = await deleteWorkflowProcess({ id: row.id });