From 0db8c9b94a9ac655549d5eba5c2a6c92ac386c06 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期四, 08 十月 2026 11:20:56 +0800
Subject: [PATCH] 提交最新代码

---
 culture/src/views/pedigree-chart/addProgenitor.vue |  820 ++++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 619 insertions(+), 201 deletions(-)

diff --git a/culture/src/views/pedigree-chart/addProgenitor.vue b/culture/src/views/pedigree-chart/addProgenitor.vue
index 003bc00..c1a9b26 100644
--- a/culture/src/views/pedigree-chart/addProgenitor.vue
+++ b/culture/src/views/pedigree-chart/addProgenitor.vue
@@ -1,40 +1,54 @@
 <template>
   <div>
-    <el-form
-      :model="form"
-      :rules="rules"
-      ref="pedigreeForm"
-      label-position="top"
-      class="strain-form"
-    >
+    <div class="header-title" style="width: 100%;">
+      <div class="header-title-left">
+        <img src="@/assets/public/headercard.png" />
+        <div>所属项目组</div>
+      </div>
+      <div class="header-title-right">
+        <el-button @click="showChoose = true" :disabled="!!$route.query.id" class="el-icon-circle-plus-outline" type="primary">
+          选择项目组</el-button>
+      </div>
+    </div>
+    <Table :height="null" :queryForm="queryForm" :total="0" :data="projectData" style="margin-bottom: 20px">
+      <template>
+        <el-table-column prop="teamName" label="项目组名称" />
+        <el-table-column prop="personCharge" label="项目负责人" />
+        <el-table-column prop="staff" label="项目组成员" />
+        <el-table-column prop="createTime" label="创建时间" />
+      </template>
+    </Table>
+    <el-form :model="form" :rules="rules" ref="pedigreeForm" label-position="top" class="strain-form">
       <div class="card">
         <div class="form-items-row">
           <el-form-item label="传代菌种编号" prop="strainCode" required>
-            <el-input
-              v-model="form.strainCode"
-              placeholder="请输入"
-              class="fixed-width-input"
-            ></el-input>
+            <el-input v-model="form.strainCode" :disabled="!!$route.query.id" placeholder="请输入"
+              class="fixed-width-input"></el-input>
           </el-form-item>
           <el-form-item label="传代菌种名称" prop="strainName" required>
-            <el-input
-              v-model="form.strainName"
-              placeholder="请输入"
-              class="fixed-width-input"
-            ></el-input>
+            <el-input v-model="form.strainName" placeholder="请输入" :disabled="!!$route.query.id"
+              class="fixed-width-input"></el-input>
           </el-form-item>
         </div>
       </div>
-      <div class="card" style="margin-top: 30px; display: block">
-        <Table
-          :height="null"
-          :total="total"
-          :data="tableData"
-          :queryForm="queryForm"
-          @handleCurrentChange="handleCurrentChange"
-          @handleSizeChange="handleSizeChange"
-        >
-          <el-table-column label="菌种实验员" prop="experimenter" />
+      <div class="card" style="margin-top: 30px; display: block" v-if="roleType != 4">
+        <div class="title" style="padding: 25px 0">待确认传代计划数</div>
+        <Table :height="null" :total="newTotal" :data="newTableData" :queryForm="newQueryForm"
+          @handleCurrentChange="handleNewCurrentChange" @handleSizeChange="handleNewSizeChange">
+          <el-table-column label="菌种工程师" prop="createBy" />
+          <el-table-column label="菌种编号" prop="strainCode" />
+          <el-table-column label="菌种名称" prop="strainName" />
+          <el-table-column label="传代计划数量" prop="generationCount" />
+          <el-table-column label="操作" v-if="roleType == 2">
+            <template #default="{ row }">
+              <el-button type="text" @click="handleNewConfirm(row)">确认</el-button>
+            </template>
+          </el-table-column>
+        </Table>
+        <div class="title" style="padding: 25px 0">待确认入库菌种列表</div>
+        <Table :height="null" :total="total" :data="tableData" :queryForm="queryForm"
+          @handleCurrentChange="handleCurrentChange" @handleSizeChange="handleSizeChange">
+          <el-table-column label="菌种工程师" prop="experimenter" />
           <el-table-column label="菌种编号" prop="strainCode" />
           <el-table-column label="菌种名称" prop="strainName" />
           <el-table-column label="保存/废弃">
@@ -42,12 +56,10 @@
               {{ row.status === 1 ? "保存" : "废弃" }}
             </template>
           </el-table-column>
-          <el-table-column label="菌种保存/废弃时间" prop="storageTime" />
-          <el-table-column label="操作">
+          <el-table-column label="菌种入库时间/菌种废弃时间" prop="createTime" />
+          <el-table-column label="操作" v-if="roleType == 2">
             <template #default="{ row }">
-              <el-button type="text" @click="handleConfirm(row)"
-                >确认入库</el-button
-              >
+              <el-button type="text" @click="handleConfirm(row)">确认入库</el-button>
             </template>
           </el-table-column>
         </Table>
@@ -57,46 +69,38 @@
         <div class="header">
           <div class="title">菌种传代生产谱系图</div>
           <div class="option-btn">
-            <el-button type="primary" class="el-icon-plus" @click="addNode">
-              新增</el-button
-            >
-            <el-button type="primary" @click="setGenerationPlan"
-              >设置传代计划数</el-button
-            >
+            <el-button type="primary" class="el-icon-plus" @click="addNode" :disabled="editBoolean" v-if="!isReadOnly && (roleType == 3 || roleType == 1)">
+              <!-- v-if="$route.query.type != 1" -->
+              新增</el-button>
+            <el-button type="primary" v-if="!isReadOnly && (roleType == 3 || roleType == 1)" :disabled="editBoolean"
+              @click="setGenerationPlan">设置传代计划数</el-button>
             <el-button type="primary" @click="showDetail">详情</el-button>
-            <el-button type="primary" @click="handleEdit">编辑</el-button>
-            <el-button type="primary" @click="handleDelete">删除</el-button>
+            <el-button type="primary" @click="handleEdit" v-if="!isReadOnly && (roleType == 1 || roleType == 3)" :disabled="editBoolean">编辑</el-button>
+            <el-button type="primary" @click="handleDelete" v-if="!isReadOnly && (roleType == 1 || roleType == 3)" :disabled="editBoolean">删除</el-button>
           </div>
         </div>
 
         <div class="strain-flow-chart">
-          <div id="mountNode"></div>
+          <div ref="mountNode" class="mount-node"></div>
         </div>
-        <el-button
-          v-if="!$route.query.id"
-          type="primary"
-          @click="handleSubmit"
-          style="width: 150px"
-          >保存</el-button
-        >
+        <div v-if="!isReadOnly && (roleType == 1 || roleType == 3)">
+          <el-button type="primary" @click="handleSubmit('1')" style="width: 150px" :disabled="editBoolean">保存</el-button>
+          <el-button type="primary" @click="handleSubmit('2')" style="width: 150px; margin-left: 20px" :disabled="editBoolean">提交</el-button>
+        </div>
       </div>
     </el-form>
 
-    <AddAncestor ref="addAncestor" @addNodeSign="addNodeSign" />
-    <PlanForm ref="planForm" @addNodeSign="addNodeSign" />
-    <AddSublevelForm ref="addSublevelForm" @addNodeSign="addNodeSign" />
-    <ConfirmStorageDialog
-      name="接种操作人签字"
-      :visible.sync="confirmStorageDialogVisible"
-      @confirm="handleSignatureConfirm"
-    />
+    <AddAncestor :key="pageInstanceKey" ref="addAncestor" @addNodeSign="addNodeSign" />
+    <PlanForm :key="pageInstanceKey" ref="planForm" @addNodeSign="addNodeSign" />
+    <AddSublevelForm :key="pageInstanceKey" ref="addSublevelForm" @addNodeSign="addNodeSign" />
+    <ConfirmStorageDialog :key="`signature-${pageInstanceKey}`" name="接种操作人签字" :visible.sync="confirmStorageDialogVisible"
+      @confirm="handleSignatureConfirm" />
     <!-- 菌种工程师 -->
-    <ConfirmStorageDialog
-      name="菌种保藏人签字"
-      text="是否确认该项菌种信息入库"
-      :visible.sync="storageVisible"
-      @confirm="handleSignatureConfirm1"
-    />
+    <ConfirmStorageDialog :key="`storage-${pageInstanceKey}`" name="菌种保藏人签字" text="是否确认该项菌种信息入库" :visible.sync="storageVisible"
+      @confirm="handleSignatureConfirm1" />
+    <!-- 传代数审批 -->
+    <ApprovalCount :key="`approval-${pageInstanceKey}`" ref="approvalCount" @addNodeSign="sureApprovalCountSign" />
+    <chooseProject :key="`project-${pageInstanceKey}`" @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
   </div>
 </template>
 
@@ -110,23 +114,33 @@
   add,
   getDetail,
   addProgenitorChild,
+  addCount,
   addProgenitor,
   pageListDetail,
+  pageListCountDetail,
   confirmStorage,
   deleteNode,
   updateChild,
+  edit,
+  confirmCount,
 } from "./service";
+import ApprovalCount from "./progenitorComponents/approvalCount.vue";
+import ChooseProject from "@/components/chooseProject/index.vue";
 
 export default {
   name: "AddPedigree",
   components: {
+    ChooseProject,
     PlanForm,
     AddAncestor,
     AddSublevelForm,
     ConfirmStorageDialog,
+    ApprovalCount,
   },
   data() {
     return {
+      showChoose: false,
+      projectData: [], // 存储选中的项目组数据
       queryForm: {
         pageSize: 10,
         pageNum: 1,
@@ -164,13 +178,32 @@
       tableData: [],
       confirmStorageDialogVisible: false,
       storageVisible: false,
+      editBoolean: false,//编辑控制
       total: 0,
       current: 1,
       size: 10,
       comfirmId: "",
+      roleType: Number(
+        JSON.parse(sessionStorage.getItem("userInfo")).roleType || 1
+      ), // 1.超级管理员 2.审批人 3.工程师 4.实验员
+      // 2.0
+      newTotal: 0,
+      newCurrent: 1,
+      newSize: 10,
+      newTableData: [],
+      newQueryForm: {
+        pageSize: 10,
+        pageNum: 1,
+      },
+      activeRouteKey: "",
+      graphLoadId: 0,
+      pageInstanceKey: 0,
     };
   },
   computed: {
+    isReadOnly() {
+      return this.$route.path.includes('detail') || this.$route.query.mode === 'detail';
+    },
     canAddNode() {
       // 如果没有节点,可以新增母代
       if (this.graphData.nodes.length === 0) {
@@ -183,48 +216,251 @@
       return false;
     },
   },
-  created() {
+  watch: {
+    '$route': {
+      immediate: true,
+      handler(to) {
+        if (!["AddProgenitor", "DetailProgenitor"].includes(to.name)) {
+          return;
+        }
+        console.log('变动');
+        const routeKey = to.fullPath;
+        const routeChanged = this.activeRouteKey && this.activeRouteKey !== routeKey;
+        this.activeRouteKey = routeKey;
+        if (routeChanged || !to.query.id) {
+          this.resetPageState();
+        }
+        if (this.graph && to.query.id) {
+          this.reloadData();
+        }
+
+        this.editBoolean = this.shouldDisableEditing(to.query);
+      }
+    }
+  },
+  mounted() {
+    this.resetMountNode();
     if (this.$route.query.id) {
       this.reloadData();
     }
   },
-  mounted() {
-    this.initGraph();
-    this.initEvents();
-  },
   beforeDestroy() {
-    this.graph?.destroy();
-    window.removeEventListener("resize", this.handleResize);
+    this.destroyGraph();
   },
   methods: {
+    shouldDisableEditing(query = this.$route.query) {
+      const status = query && query.status;
+      return Number(this.roleType) !== 1
+          && status !== undefined
+          && status !== null
+          && status !== ""
+          && Number(status) !== 1;
+    },
+    destroyGraph() {
+      window.removeEventListener("resize", this.handleResize);
+      if (this.graph && !this.graph.get("destroyed")) {
+        this.graph.destroy();
+      }
+      this.graph = null;
+
+      const container = this.$refs.mountNode;
+      if (container) {
+        while (container.firstChild) {
+          container.removeChild(container.firstChild);
+        }
+      }
+    },
+    resetMountNode() {
+      this.destroyGraph();
+      if (!this.$refs.mountNode) return;
+      this.initGraph();
+      this.initEvents();
+    },
+    resetPageState() {
+      this.pageInstanceKey += 1;
+      this.form = {
+        strainCode: "",
+        strainName: "",
+        generationType: "2",
+      };
+      this.projectData = [];
+      this.tableData = [];
+      this.newTableData = [];
+      this.total = 0;
+      this.current = 1;
+      this.size = 10;
+      this.newTotal = 0;
+      this.newCurrent = 1;
+      this.newSize = 10;
+      this.queryForm = { pageSize: 10, pageNum: 1 };
+      this.newQueryForm = { pageSize: 10, pageNum: 1 };
+      this.showChoose = false;
+      this.dialogVisible = false;
+      this.confirmStorageDialogVisible = false;
+      this.storageVisible = false;
+      this.nodeData = {};
+      this.nodeType = "";
+      this.isAddingNode = false;
+      this.showDiscarded = false;
+      this.editBoolean = this.shouldDisableEditing();
+      this.resetGraphData();
+      this.$nextTick(() => {
+        this.$refs.pedigreeForm && this.$refs.pedigreeForm.clearValidate();
+      });
+    },
+    resetGraphData() {
+      this.graphLoadId += 1;
+      this.graphData = {
+        nodes: [],
+        edges: [],
+      };
+      this.selectedNode = null;
+      this.nodeCount = 0;
+
+      if (this.graph) {
+        this.graph.changeData({ nodes: [], edges: [] });
+        this.graph.render();
+      }
+    },
+    getProjectData(data) {
+      this.projectData = [data]; // 将选中的项目组数据存储到数组中
+      this.showChoose = false;
+      this.form.projectId = this.projectData[0].id;
+    },
     handleDelete() {
+      console.log('handleDelete selectedNode', this.selectedNode)
       if (!this.selectedNode) {
         this.$message.warning("请先选择节点");
         return;
       }
+      if (
+        this.selectedNode &&
+        this.selectedNode.data &&
+        this.selectedNode.data.codeStatus !== null &&
+        this.selectedNode.data.codeStatus == 2
+      ) {
+        this.$message.warning("谱系图已提交,不能删除");
+        return;
+      }
+
       this.$confirm("确定删除该节点吗?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning",
       }).then(() => {
-        deleteNode({ id: this.selectedNode.id }).then((res) => {
-          if (res.code == 200) {
-            this.$message.success("删除成功");
-            this.reloadData();
-          }
-        });
+        // 判断是新增模式还是编辑模式
+        if (!this.$route.query.id) {
+          // 新增模式:前端直接删除节点
+          this.deleteNodeFromGraph(this.selectedNode.id);
+          this.$message.success("删除成功");
+        } else {
+          // 编辑模式:调用后端删除接口
+          deleteNode({ id: this.selectedNode.id }).then((res) => {
+            if (res.code == 200) {
+              this.$message.success("删除成功");
+              this.reloadData();
+            }
+          });
+        }
       });
     },
+
+    // 前端删除节点方法
+    deleteNodeFromGraph(nodeId) {
+      // 递归删除节点
+      const deleteNodeRecursive = (nodes, targetId) => {
+        for (let i = 0; i < nodes.length; i++) {
+          if (nodes[i].id === targetId) {
+            // 找到目标节点,直接删除
+            nodes.splice(i, 1);
+            return true;
+          }
+          // 在子节点中查找
+          if (nodes[i].children && nodes[i].children.length > 0) {
+            if (deleteNodeRecursive(nodes[i].children, targetId)) {
+              // 如果删除的是传代计划数的子节点(母代),需要更新计划数的当前数量
+              if (nodes[i].label === '传代计划数') {
+                nodes[i].currentCount = nodes[i].children.length;
+              }
+              return true;
+            }
+          }
+        }
+        return false;
+      };
+
+      // 执行删除
+      const deleted = deleteNodeRecursive(this.graphData.nodes, nodeId);
+
+      if (deleted) {
+        // 清空选中节点
+        this.selectedNode = null;
+
+        // 转换树形数据为G6可用的格式
+        const convertToG6Data = (nodes) => {
+          const g6Nodes = [];
+          const g6Edges = [];
+
+          const processNode = (node, parentId = null) => {
+            g6Nodes.push({
+              id: node.id,
+              label: node.label,
+              number: node.number,
+              data: node.data,
+              isDiscarded: node.isDiscarded,
+              style: node.style,
+              planCount: node.planCount,
+              currentCount: node.currentCount,
+            });
+
+            if (parentId) {
+              g6Edges.push({
+                source: parentId,
+                target: node.id,
+                style: {
+                  stroke: "rgba(4, 156, 154, 1)",
+                  lineWidth: 1,
+                },
+              });
+            }
+
+            if (node.children && node.children.length > 0) {
+              node.children.forEach((child) => processNode(child, node.id));
+            }
+          };
+
+          nodes.forEach((node) => processNode(node));
+          return { nodes: g6Nodes, edges: g6Edges };
+        };
+
+        // 更新图表
+        const g6Data = convertToG6Data(this.graphData.nodes);
+        this.graph.changeData(g6Data);
+        this.graph.render();
+        this.graph.fitView();
+      }
+    },
     handleEdit() {
+      console.log('handleEdit selectedNode', this.selectedNode)
       if (!this.selectedNode) {
         this.$message.warning("请先选择节点");
         return;
+      }
+      if (
+        this.selectedNode &&
+        this.selectedNode.data &&
+        this.selectedNode.data.codeStatus != null &&
+        this.selectedNode.data.codeStatus == 2
+      ) {
+        this.$message.warning("谱系图已提交,不能编辑");
+        return
       }
 
       const nodeModel = this.selectedNode;
 
       if (nodeModel.label === "祖代") {
         this.$refs.addAncestor.openInitData({
+          id: nodeModel.id,
           ...nodeModel.data,
           formStatus: "edit",
         });
@@ -268,7 +504,6 @@
           current: this.current,
           size: this.size,
         });
-
         if (listRes.code === 200) {
           this.tableData = listRes.data.records;
           this.total = listRes.data.total;
@@ -282,9 +517,63 @@
         this.$message.error("数据加载失败");
       }
     },
+    handleNewConfirm(row) {
+      console.log("row row", row);
+      this.$refs.approvalCount.openInitData(row);
+    },
+    // 处理每页显示数量变化
+    handleNewSizeChange(val) {
+      this.newSize = val;
+      this.newQueryForm.pageSize = val;
+      this.getNewList();
+    },
+
+    // 处理页码变化
+    handleNewCurrentChange(val) {
+      this.newCurrent = val;
+      this.newQueryForm.pageNum = val;
+      this.getNewList();
+    },
+    async getNewList() {
+      try {
+        // 获取列表数据
+        const listRes = await pageListCountDetail({
+          id: this.$route.query.id,
+          current: this.current,
+          size: this.size,
+        });
+        console.log("待确认传代计划数 待确认传代计划数", listRes);
+        if (listRes.code === 200) {
+          this.newTableData = listRes.data.records;
+          this.newTotal = listRes.data.total;
+          this.newCurrent = listRes.data.current;
+          this.newSize = listRes.data.size;
+        }
+
+        // ... 其他现有的 reloadData 代码 ...
+      } catch (error) {
+        console.error("Failed to reload data:", error);
+        this.$message.error("数据加载失败");
+      }
+    },
     async reloadData() {
-      this.getList();
+      this.resetPageState();
+      this.resetMountNode();
+      const graphLoadId = this.graphLoadId;
+      const routeKey = this.$route.fullPath;
+      await this.getList();
+      await this.getNewList();
+      if (graphLoadId !== this.graphLoadId || routeKey !== this.$route.fullPath) {
+        return;
+      }
+      if (!this.$route.query.id) {
+        return
+      }
       getDetail({ id: this.$route.query.id }).then((res) => {
+        if (graphLoadId !== this.graphLoadId || routeKey !== this.$route.fullPath) {
+          return;
+        }
+        this.projectData = res.tprojectTeamList
         const detailData = res.pedigreeChartParentAllDetailDTO;
         // 设置基础表单数据
         this.form = {
@@ -295,41 +584,42 @@
         // 递归处理节点数据,构建树形结构
         function processNode(node, parentType = null) {
           // label 逻辑与新增时保持一致
-          let label = "";
-          if (node.type === 2) {
-            label = "传代计划数";
-          } else if (parentType === 2) {
-            label = "母代";
-          } else {
-            label = "祖代";
-          }
-          const processedNode = {
-            id: node.id,
-            label,
-            number: node.strainCode,
-            data: node,
-            isDiscarded: node.status === 1,
-            style: {
-              fill: node.status === 1 ? "#00B5AA" : "#999",
-              opacity: node.status === 1 ? 0.6 : 0.3,
-            },
-            children: [],
-          };
+         let roleType= Number(JSON.parse(sessionStorage.getItem("userInfo")).roleType || 1)
+            let label = "";
+            if (node.type === 2) {
+              label = "传代计划数";
+            } else if (parentType === 2) {
+              label = "母代";
+            } else {
+              label = "祖代";
+            }
+            const processedNode = {
+              id: node.id,
+              label,
+              number: node.strainCode,
+              data: node,
+              isDiscarded: node.status === 1,
+              style: {
+                fill: node.status === 1 ? "#00B5AA" : "#999",
+                opacity: node.status === 1 ? 0.6 : 0.3,
+              },
+              children: [],
+            };
 
-          if (node.type === 2) {
-            processedNode.planCount = node.generationCount;
-            processedNode.currentCount = node.children
-              ? node.children.length
-              : 0;
-          }
+            if (node.type === 2) {
+              processedNode.planCount = node.generationCount;
+              processedNode.currentCount = node.children
+                ? node.children.length
+                : 0;
+            }
 
-          if (node.children && node.children.length > 0) {
-            processedNode.children = node.children.map((child) =>
-              processNode(child, node.type)
-            );
-          }
-
-          return processedNode;
+            if (node.children && node.children.length > 0) {
+              // 审批人需要查看完整谱系,包括仍处于保存状态的节点。
+              processedNode.children = node.children
+                .filter((child) => roleType === 2 || child.codeStatus == 2 || (child.codeStatus == 1 && roleType === 3))
+                .map((child) => processNode(child, node.type));
+            }
+            return processedNode;
         }
 
         // 构建完整的树形结构,添加空值校验
@@ -339,45 +629,9 @@
 
         // 在数据加载完成后重新渲染图表
         this.$nextTick(() => {
-          if (this.graph) {
-            // 转换树形数据为G6可用的格式
-            const convertToG6Data = (nodes) => {
-              const g6Nodes = [];
-              const g6Edges = [];
-
-              const processNode = (node, parentId = null) => {
-                g6Nodes.push({
-                  id: node.id,
-                  label: node.label,
-                  number: node.number,
-                  data: node.data,
-                  isDiscarded: node.isDiscarded,
-                  style: node.style,
-                  planCount: node.planCount,
-                  currentCount: node.currentCount,
-                });
-
-                if (parentId) {
-                  g6Edges.push({
-                    source: parentId,
-                    target: node.id,
-                    style: {
-                      stroke: "rgba(4, 156, 154, 1)",
-                      lineWidth: 1,
-                    },
-                  });
-                }
-
-                if (node.children && node.children.length > 0) {
-                  node.children.forEach((child) => processNode(child, node.id));
-                }
-              };
-
-              nodes.forEach((node) => processNode(node));
-              return { nodes: g6Nodes, edges: g6Edges };
-            };
-
-            const g6Data = convertToG6Data(this.graphData.nodes);
+          console.log('this.graphData.nodes',this.graphData.nodes)
+          if (this.graph && this.graphData.nodes.length > 0) {
+            const g6Data = this.convertToG6Data(this.graphData.nodes);
             this.graph.changeData(g6Data);
             this.graph.render();
             this.graph.fitView();
@@ -385,36 +639,102 @@
         });
       });
     },
+    // 转换树形数据为G6可用的格式
+    convertToG6Data(nodes) {
+      const g6Nodes = [];
+      const g6Edges = [];
+
+      const processNode = (node, parentId = null) => {
+        g6Nodes.push({
+          id: node.id,
+          label: node.label,
+          number: node.number,
+          data: node.data,
+          isDiscarded: node.isDiscarded,
+          style: node.style,
+          planCount: node.planCount,
+          currentCount: node.currentCount,
+        });
+
+        if (parentId) {
+          g6Edges.push({
+            source: parentId,
+            target: node.id,
+            style: {
+              stroke: "rgba(4, 156, 154, 1)",
+              lineWidth: 1,
+            },
+          });
+        }
+
+        if (node.children && node.children.length > 0) {
+          node.children.forEach((child) => processNode(child, node.id));
+        }
+      };
+
+      nodes.forEach((node) => processNode(node));
+      return { nodes: g6Nodes, edges: g6Edges };
+    },
     addNodeSign(value, type) {
       this.nodeData = value;
+      //todo 同步画布数据 nodeData.strainType
       this.nodeType = type;
+      // this.$refs.addAncestor.closeDialog()
+      this.$refs.addSublevelForm.closeDialog();
       this.confirmStorageDialogVisible = true;
     },
-    handleSubmit() {
+    // 传代计划数  审批
+    sureApprovalCountSign(value) {
+      console.log("value", value);
+      confirmCount({
+        id: value.id,
+        preserveSignature: value.preserveSignature,
+      }).then((res) => {
+        if (res.code == 200) {
+          this.$message.success("审批传代计划数成功");
+          this.$refs.approvalCount.closeDialog();
+          this.reloadData();
+        }
+      });
+    },
+    handleSubmit(type) {
       this.$refs.pedigreeForm.validate((valid) => {
         if (valid) {
           // 递归处理节点数据,将data对象的内容提取到上一级并删除data属性
-          const processNodeData = (nodes) => {
+          const processNodeData = (nodes, type) => {
             return nodes.map((node) => {
               const { data, children, ...rest } = node;
               const processedNode = {
                 ...rest,
                 ...data, // 将data对象的内容展开到当前节点
-                children: children ? processNodeData(children) : [],
+                codeStatus: type == 2 ? '2' : data.codeStatus || type,
+                children: children ? processNodeData(children, type) : [],
               };
               return processedNode;
             });
           };
 
           // 获取基础表单数据
-          const baseData = {
-            parent: { ...this.form },
-            one: processNodeData(this.graphData.nodes),
+          let baseData = {
+            parent: { ...this.form, status: type },
+            one: processNodeData(this.graphData.nodes, type),
           };
+          console.log("baseData baseData", baseData);
+          // return
+          if (this.$route.query.id) {
+            baseData.parent.id = this.$route.query.id;
+            edit({ ...baseData, id: this.$route.query.id }).then((res) => {
+              if (res.code == 200) {
+                this.$message.success("编辑成功");
+                this.$closeCurrentView('/strain/pedigree-vhart');
+              }
+            });
+            return;
+          }
           add(baseData).then((res) => {
             if (res.code == 200) {
               this.$message.success("保存成功");
-              this.$router.back();
+              this.$closeCurrentView('/strain/pedigree-vhart');
             }
           });
         }
@@ -422,10 +742,9 @@
     },
     handleDraft() {
       // 实现存草稿逻辑
-      console.log("save draft", this.form);
     },
     handleCancel() {
-      this.$router.back();
+      this.$closeCurrentView('/strain/pedigree-vhart');
     },
     handleSignatureConfirm(signatureImage) {
       this.confirmStorageDialogVisible = false;
@@ -452,6 +771,21 @@
     },
     addNode() {
       // 如果没有节点,新增祖代
+      console.log("选择的节点", this.selectedNode);
+      // if (this.selectedNode && this.selectedNode.data && this.selectedNode.data.auditStatus && this.selectedNode.data.auditStatus != 2) {
+      //   this.$message.warning("该传代计划数未审核,请先审核");
+      //   return;
+      // }
+      if (
+        this.selectedNode &&
+        this.selectedNode.data &&
+        this.selectedNode.data.auditStatus !== null &&
+        this.selectedNode.data.auditStatus != 2
+      ) {
+        this.$message.warning("该传代计划数未审核,请先审核");
+        return;
+      }
+
       if (this.graphData.nodes.length === 0) {
         this.$refs.pedigreeForm.validate((valid) => {
           if (valid) {
@@ -470,6 +804,15 @@
             });
           }
         });
+        return;
+      }
+      //
+      if (
+        !this.$route.query.id &&
+        this.selectedNode &&
+        this.selectedNode.label === "传代计划数"
+      ) {
+        this.$message.warning("一次只能添加一个传代");
         return;
       }
 
@@ -524,20 +867,27 @@
       }
     },
     handleAddParent(value) {
+      console.log('handleAddParent 编辑修改', value);
       if (value.formStatus == "edit") {
-        updateChild(value).then((res) => {
+        updateChild({ ...value, codeStatus: '1' }).then((res) => {
           if (res.code == 200) {
             this.$message.success("操作成功");
             this.$refs.addAncestor.closeDialog();
-            this.reloadData();
+
+            // this.reloadData();
+            // 1. 如果是编辑模式(前端编辑),先删除旧节点
+            if (this.selectedNode) {
+              // 删除旧节点
+              this.deleteNodeFromGraph(this.selectedNode.id);
+            }
           }
         });
-        return;
+        // return;
       }
       if (this.$route.query.id) {
         value.pedigreeChartId = this.$route.query.id;
         value.parentId = "0";
-        addProgenitor(value).then((res) => {
+        addProgenitor({ ...value, codeStatus: '1' }).then((res) => {
           if (res.code == 200) {
             this.$message.success("操作成功");
             this.$refs.addAncestor.closeDialog();
@@ -569,8 +919,9 @@
       this.$refs.form.resetFields();
     },
     handleAddSublevel(value) {
+      console.log('222222222222 编辑编辑', value)
       if (value.formStatus == "edit") {
-        updateChild(value).then((res) => {
+        updateChild({ ...value, codeStatus: '1' }).then((res) => {
           if (res.code == 200) {
             this.$message.success("操作成功");
             this.$refs.addSublevelForm.closeDialog();
@@ -580,7 +931,7 @@
         return;
       }
       if (this.$route.query.id) {
-        addProgenitor(value).then((res) => {
+        addProgenitor({ ...value, codeStatus: '1' }).then((res) => {
           if (res.code === 200) {
             this.$message.success("操作成功");
             this.$refs.addSublevelForm.closeDialog();
@@ -755,6 +1106,10 @@
       }
     },
     setGenerationPlan() {
+      if (this.newTableData.length != 0) {
+        this.$message.warning("有未审核的待确认传代计划数,请先审核");
+        return;
+      }
       if (!this.selectedNode) {
         this.$message.warning("请先选择节点");
         return;
@@ -784,30 +1139,46 @@
         this.$message.warning("该节点已经存在传代计划数节点");
         return;
       }
-      console.log({
-        ...nodeModel.data,
-        label: nodeModel.label,
-      });
 
       this.$refs.planForm.openInitData({
         ...nodeModel.data,
         label: nodeModel.label,
+        formStatus: "add",
       });
     },
     handleAddPlan(value) {
       if (this.$route.query.id) {
-        let params = {
-          parentId: value.id,
-          generationCount: value.generationCount,
-          vaccinateSignature: value.vaccinateSignature,
-        };
-        addProgenitorChild(params).then((res) => {
-          if (res.code === 200) {
-            this.$message.success("操作成功");
-            this.$refs.planForm.closeDialog();
-            this.reloadData();
-          }
-        });
+        console.log('value', value)
+
+        if (value.formStatus == "add") {
+          let params = {
+            parentId: value.id,
+            generationCount: value.generationCount,
+            vaccinateSignature: value.vaccinateSignature,
+          };
+          addCount({ ...params, codeStatus: '1' }).then((res) => {
+            if (res.code === 200) {
+              this.$message.success("操作成功");
+              this.$refs.planForm.closeDialog();
+              this.reloadData();
+            }
+          });
+        } else {
+          let params = {
+            id: value.id,
+            generationCount: value.generationCount,
+            vaccinateSignature: value.vaccinateSignature,
+          };
+          addProgenitorChild({ ...params, codeStatus: '1' }).then((res) => {
+            if (res.code === 200) {
+              this.$message.success("操作成功");
+              this.$refs.planForm.closeDialog();
+              this.reloadData();
+            }
+          });
+        }
+
+
         return;
       }
 
@@ -918,7 +1289,8 @@
       }
     },
     initGraph() {
-      const container = document.getElementById("mountNode");
+      const container = this.$refs.mountNode;
+      if (!container) return;
       const width = container.scrollWidth;
       const height = container.scrollHeight || 600;
 
@@ -936,19 +1308,19 @@
           const titleFill = isDiscarded
             ? "rgba(245, 248, 250, 1)"
             : cfg.selected
-            ? "l(0) 0:#0ACBCA 1:#049C9A"
-            : "l(0) 0:#0ACBCA 1:#049C9A";
+              ? "l(0) 0:#0ACBCA 1:#049C9A"
+              : "l(0) 0:#0ACBCA 1:#049C9A";
           const contentFill = isDiscarded
             ? "rgba(245, 248, 250, 1)"
             : cfg.selected
-            ? "rgba(4,156,154,0.2)"
-            : "rgba(4,156,154,0.1)";
+              ? "rgba(4,156,154,0.2)"
+              : "rgba(4,156,154,0.1)";
           const textFill = isDiscarded ? "rgba(144, 147, 153, 1)" : "#049C9A";
           const stroke = isDiscarded
             ? "#DCDFE6"
             : cfg.selected
-            ? "#049C9A"
-            : "transparent";
+              ? "#049C9A"
+              : "transparent";
 
           // 创建渐变
           const gradient = group.addShape("rect", {
@@ -990,7 +1362,7 @@
                 x: 0,
                 y: -totalHeight / 2 + titleHeight / 2,
                 fill: isDiscarded ? "rgba(144, 147, 153, 1)" : "#fff",
-                fontSize: 12,
+                fontSize: 14,
                 textAlign: "center",
                 textBaseline: "middle",
                 fontWeight: "bold",
@@ -1005,10 +1377,17 @@
           if (cfg.label === "传代计划数") {
             content = `${cfg.planCount || 0}`;
           } else if (cfg.number) {
-            content =
-              cfg.label === "母代"
-                ? `代传菌种编号:${cfg.number}`
-                : `接种菌种编号:${cfg.number}`;
+            // 获取类型名称
+            let typeName = "接种菌种";
+            if (cfg.data && cfg.data.strainType) {
+              const typeMap = {
+                1: "原始祖代菌株SO",
+                2: "分离菌落 CO",
+                3: "祖代菌株 O",
+              };
+              typeName = typeMap[cfg.data.strainType] || "接种菌种";
+            }
+            content = `${typeName}编号:${cfg.number}`;
           }
 
           if (content) {
@@ -1018,7 +1397,7 @@
                 x: 0,
                 y: -totalHeight / 2 + titleHeight + gap + contentHeight / 2,
                 fill: textFill,
-                fontSize: 10,
+                fontSize: 11,
                 textAlign: "center",
                 textBaseline: "middle",
                 cursor: "move",
@@ -1043,7 +1422,7 @@
       });
 
       this.graph = new G6.Graph({
-        container: "mountNode",
+        container,
         width,
         height,
         fitView: true,
@@ -1185,11 +1564,11 @@
         evt.preventDefault(); // 阻止默认触摸行为
         const node = evt.item;
         const nodeModel = node.getModel();
-        // 如果节点已废弃,不允许任何操作
-        if (!nodeModel.isDiscarded) {
-          this.$message.warning("该节点已废弃,不能进行操作");
-          return;
-        }
+        // 如果节点已废弃,不允许任何操作    放开
+        // if (!nodeModel.isDiscarded) {
+        //   this.$message.warning("该节点已废弃,不能进行操作");
+        //   return;
+        // }
         // 更新选中节点
         this.selectedNode = nodeModel;
         // 更新节点选中状态
@@ -1307,7 +1686,8 @@
     },
     handleResize() {
       if (this.graph) {
-        const container = document.getElementById("mountNode");
+        const container = this.$refs.mountNode;
+        if (!container) return;
         const width = container.scrollWidth;
         const height = container.scrollHeight || 600;
         this.graph.changeSize(width, height);
@@ -1373,6 +1753,40 @@
   }
 }
 
+
+.header-title {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 13px;
+
+  .header-title-left {
+    display: flex;
+    align-items: center;
+    gap: 13px;
+
+    img {
+      width: 12px;
+      height: 19px;
+    }
+
+    div {
+      flex-shrink: 0;
+      font-weight: bold;
+      font-size: 18px;
+      color: #222222;
+      line-height: 27px;
+      font-family: 'Source Han Sans CN Bold Bold';
+
+      &:before {
+        content: '*';
+        color: #F56C6C;
+        margin-right: 4px;
+      }
+    }
+  }
+}
+
 .strain-form {
   width: 100%;
 
@@ -1403,6 +1817,10 @@
   }
 }
 
+.title {
+  font-size: 18px;
+}
+
 .end-btn {
   margin-top: 20px;
   display: flex;
@@ -1426,7 +1844,7 @@
     }
   }
 
-  #mountNode {
+  .mount-node {
     flex: 1;
     width: 100%;
     min-height: 500px;

--
Gitblit v1.7.1