13404089107
2 天以前 993e5fd593398926af72af660cb5ed6aba8e4e2b
culture/src/views/pedigree-chart/add.vue
@@ -1,93 +1,117 @@
<template>
  <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="strainSource" required>
          <div class="flex-row">
            <div class="input-wrapper">
              <el-input
                v-model="form.strainSource"
                placeholder="请输入"
                class="fixed-width-input"
              ></el-input>
  <div>
    <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="菌种源" required>
            <div class="flex-row">
              <div class="input-wrapper">
                <el-form-item prop="strainSourceStart" style="margin-bottom: 0;">
                  <el-input v-model="form.strainSourceStart" placeholder="请输入" class="fixed-width-input"></el-input>
                </el-form-item>
              </div>
              <span class="form-text">代—</span>
              <div class="input-wrapper">
                <el-form-item prop="strainSourceEnd" style="margin-bottom: 0;">
                  <el-input v-model="form.strainSourceEnd" placeholder="请输入" class="fixed-width-input"></el-input>
                </el-form-item>
              </div>
              <span class="form-text">细胞库</span>
            </div>
            <span class="form-text">代—</span>
            <div class="input-wrapper">
              <el-input
                v-model="form.generation"
                placeholder="请输入"
                class="fixed-width-input"
              ></el-input>
            </div>
            <span class="form-text">细胞库</span>
          </div>
        </el-form-item>
        <el-form-item label="传代菌种编号" prop="strainNo" required>
          <el-input
            v-model="form.strainNo"
            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-form-item>
      </div>
    </div>
    <div class="chart">
      <div class="header">
        <div class="title">菌种传代生产谱系图</div>
        <div class="option-btn">
          <el-button type="primary" class="el-icon-plus"> 新增</el-button>
          <el-button type="primary">设置传代计划数</el-button>
          <el-button type="primary">详情</el-button>
          </el-form-item>
          <el-form-item label="传代菌种编号" prop="strainNo" required>
            <el-input v-model="form.strainNo" 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-form-item>
        </div>
      </div>
    </div>
    <div class="end-btn">
      <el-button type="primary" @click="handleSubmit">提交</el-button>
      <el-button @click="handleDraft">存草稿</el-button>
      <el-button @click="handleCancel">取消</el-button>
    </div>
    <!-- 签字确认组件 -->
    <SignatureCanvas
      :visible.sync="signatureVisible"
      @confirm="handleSignatureConfirm"
    />
  </el-form>
      <div class="card" style="margin-top: 30px;">
        <Table :height="null" :total="0" :tableData="tableData">
          <el-table-column label="接种操作人" prop="strainSource" />
          <el-table-column label="接种操作时间" prop="strainNo" />
          <el-table-column label="传代菌种编号" prop="strainName" />
          <el-table-column label="传代菌种名称" prop="strainName" />
          <el-table-column label="接种菌种编号" prop="strainName" />
          <el-table-column label="接种菌种名称" prop="strainName" />
          <el-table-column label="入库总数" prop="strainName" />
          <el-table-column label="保存/废弃" prop="strainName" />
          <el-table-column label="入库时间" prop="strainName" />
          <el-table-column label="操作">
            <template #default="{ row }">
              <el-button type="text">确认入库</el-button>
            </template>
          </el-table-column>
        </Table>
      </div>
      <div class="chart">
        <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" @click="showDetail">详情</el-button>
          </div>
        </div>
        <div class="strain-flow-chart">
          <div id="mountNode"></div>
        </div>
        <el-button type="primary" @click="handleSubmit" style="width: 150px;">保存</el-button>
      </div>
      <div class="end-btn">
        <!-- <el-button @click="handleDraft">存草稿</el-button>
        <el-button @click="handleCancel">取消</el-button> -->
      </div>
    </el-form>
    <ParentForm ref="parentForm" @addNodeSign="addNodeSign" />
    <PlanForm ref="planForm" @addNodeSign="addNodeSign" />
    <AddSublevelForm ref="addSublevelForm" @addNodeSign="addNodeSign" />
    <AddSublevelPlan ref="addSublevelPlan" @addNodeSign="addNodeSign" />
    <ConfirmStorageDialog name="接种操作人签字" :visible.sync="confirmStorageDialogVisible"
      @confirm="handleSignatureConfirm" />
    <!-- 菌种工程师 -->
    <ConfirmStorageDialog name="菌种保藏人签字" text="是否确认该项菌种信息入库" :visible.sync="storageVisible"
      @confirm="handleSignatureConfirm" />
  </div>
</template>
<script>
import SignatureCanvas from "@/components/SignatureCanvas.vue";
import G6 from '@antv/g6';
import ParentForm from "./components/ParentForm.vue";
import PlanForm from "./components/PlanForm.vue";
import AddSublevelForm from "./components/AddSublevelForm.vue";
import AddSublevelPlan from "./components/AddSublevelPlan.vue";
import ConfirmStorageDialog from "@/components/confirm-storage-dialog";
export default {
  name: "AddPedigree",
  components: {
    SignatureCanvas,
    ParentForm,
    PlanForm,
    AddSublevelForm,
    AddSublevelPlan,
    ConfirmStorageDialog
  },
  data() {
    return {
      signatureVisible: false,
      form: {
        strainSource: "",
        generation: "",
        strainSourceStart: "",
        strainSourceEnd: "",
        cellBank: "",
        strainNo: "",
        strainName: "",
        remarks: "",
      },
      rules: {
        strainSource: [
        strainSourceStart: [
          { required: true, message: "请输入菌种源", trigger: "blur" },
        ],
        strainSourceEnd: [
          { required: true, message: "请输入菌种源", trigger: "blur" },
        ],
        strainNo: [
@@ -97,13 +121,58 @@
          { required: true, message: "请输入传代菌种名称", trigger: "blur" },
        ],
      },
      graph: null,
      nodeCount: 0,
      selectedNode: null,
      graphData: {
        nodes: [],
        edges: []
      },
      // 弹窗相关数据
      dialogVisible: false,
      dialogTitle: '',
      formLabel: '',
      inputType: 'text',
      showDiscarded: false,
      isAddingNode: false,
      nodeData: {},
      nodeType: '',//1母代 2计划数 3子孙代
      tableData: [],
      confirmStorageDialogVisible: false,
      storageVisible: false
    };
  },
  computed: {
    canAddNode() {
      // 如果没有节点,可以新增母代
      if (this.graphData.nodes.length === 0) {
        return true;
      }
      // 如果选中了传代计划数节点,可以新增下一代
      if (this.selectedNode && this.selectedNode.label === '传代计划数') {
        return true;
      }
      return false;
    }
  },
  mounted() {
    this.initGraph();
    this.initEvents();
  },
  beforeDestroy() {
    this.graph?.destroy();
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    addNodeSign(value, type) {
      this.nodeData = value
      this.nodeType = type
      this.confirmStorageDialogVisible = true;
    },
    handleSubmit() {
      this.$refs.pedigreeForm.validate((valid) => {
        if (valid) {
          this.signatureVisible = true;
          this.confirmStorageDialogVisible = true;
        }
      });
    },
@@ -115,11 +184,559 @@
      this.$router.back();
    },
    handleSignatureConfirm(signatureImage) {
      this.signatureVisible = false;
      this.confirmStorageDialogVisible = false;
      if (this.nodeType === 1) {
        this.handleAddParent({ ...this.nodeData, signature: signatureImage.signature })
      } else if (this.nodeType === 2) {
        this.handleAddPlan(this.nodeData)
      } else if (this.nodeType === 3) {
        this.handleAddSublevel(this.nodeData)
      }
      // 处理提交逻辑
      console.log("submit form with signature:", this.form, signatureImage);
      this.$router.back();
    },
    initGraph() {
      const container = document.getElementById('mountNode');
      const width = container.scrollWidth;
      const height = container.scrollHeight || 600;
      // 自定义节点
      G6.registerNode('custom-node', {
        draw(cfg, group) {
          const width = 120;
          const titleHeight = 30;
          const contentHeight = 40;
          const gap = 4;
          const totalHeight = titleHeight + gap + contentHeight;
          // 根据节点状态设置颜色
          const isDiscarded = !cfg.isDiscarded;
          const titleFill = isDiscarded ? 'rgba(245, 248, 250, 1)' : (cfg.selected ? '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)');
          const textFill = isDiscarded ? 'rgba(144, 147, 153, 1)' : '#049C9A';
          const stroke = isDiscarded ? '#DCDFE6' : (cfg.selected ? '#049C9A' : 'transparent');
          // 创建渐变
          const gradient = group.addShape('rect', {
            attrs: {
              x: -width / 2,
              y: -totalHeight / 2,
              width: width,
              height: titleHeight,
              radius: 20,
              fill: titleFill,
              cursor: 'move',
              stroke: stroke,
              lineWidth: isDiscarded ? 1 : (cfg.selected ? 2 : 0),
            },
            name: 'title-box',
          });
          // 下部分 - 内容背景
          const contentBox = group.addShape('rect', {
            attrs: {
              x: -width / 2,
              y: -totalHeight / 2 + titleHeight + gap,
              width: width,
              height: contentHeight,
              fill: contentFill,
              radius: 15,
              cursor: 'move',
              stroke: stroke,
              lineWidth: isDiscarded ? 1 : (cfg.selected ? 2 : 0),
            },
            name: 'content-box',
          });
          // 标题文本
          if (cfg.label) {
            group.addShape('text', {
              attrs: {
                text: cfg.label,
                x: 0,
                y: -totalHeight / 2 + titleHeight / 2,
                fill: isDiscarded ? 'rgba(144, 147, 153, 1)' : '#fff',
                fontSize: 12,
                textAlign: 'center',
                textBaseline: 'middle',
                fontWeight: 'bold',
                cursor: 'move',
              },
              name: 'title-text',
            });
          }
          // 内容文本
          let content = '';
          if (cfg.label === '传代计划数') {
            content = `${cfg.planCount || 0}`;
          } else if (cfg.number) {
            content = cfg.label === '母代' ? `代传菌种编号:${cfg.number}` : `接种菌种编号:${cfg.number}`;
          }
          if (content) {
            group.addShape('text', {
              attrs: {
                text: content,
                x: 0,
                y: -totalHeight / 2 + titleHeight + gap + contentHeight / 2,
                fill: textFill,
                fontSize: 10,
                textAlign: 'center',
                textBaseline: 'middle',
                cursor: 'move',
              },
              name: 'content-text',
            });
          }
          return gradient;
        },
        getAnchorPoints() {
          return [
            [0.5, 0], // 上
            [1, 0.5], // 右
            [0.5, 1], // 下
            [0, 0.5], // 左
          ];
        },
        setState(name, value, item) {
          // 移除悬浮效果,保持节点样式始终一致
        },
      });
      this.graph = new G6.Graph({
        container: 'mountNode',
        width,
        height,
        fitView: true,
        fitViewPadding: 30,
        animate: false,
        enabledStack: false,
        renderer: 'canvas',
        minZoom: 0.3,
        maxZoom: 2,
        defaultZoom: 1,
        layout: {
          type: 'dagre',
          rankdir: 'LR',
          align: 'UL',
          nodesep: 30,  // 减小节点间距
          ranksep: 50,  // 减小层级间距
          controlPoints: true,
        },
        modes: {
          default: [
            {
              type: 'drag-canvas',
              enableOptimize: true,
              direction: 'both',
              scalableRange: 0.1,
              dragTimesOfScale: 0.1,
              onlyChangeComputeZoom: true,
            },
            {
              type: 'zoom-canvas',
              sensitivity: 1.5,
              enableOptimize: true,
            },
            {
              type: 'drag-node',
              enableDelegate: true,
              delegateStyle: {
                fill: '#f3f3f3',
                stroke: '#ccc',
                opacity: 0.5,
              },
              updateEdge: false,
              enableOptimize: true,
              optimizeZoom: 0.7,
              damping: 0.1,
            }
          ]
        },
        defaultNode: {
          type: 'custom-node',
          style: {
            fill: 'l(0) 0:#0ACBCA 1:#049C9A',
          },
        },
        defaultEdge: {
          type: 'cubic-horizontal',
          style: {
            stroke: 'rgba(4, 156, 154, 1)',
            lineWidth: 1,
            opacity: 0.5,
            endArrow: {
              path: G6.Arrow.triangle(6, 6),
              fill: 'rgba(4, 156, 154, 1)',
              stroke: 'rgba(4, 156, 154, 1)',
            },
          },
        },
        optimizeEdge: true,
        optimizeLayoutAnimation: true,
      });
      const canvas = this.graph.get('canvas');
      canvas.set('localRefresh', false);
      canvas.set('autoDraw', true);
      canvas.set('animating', false);
      let throttleTimer = null;
      const throttleInterval = 16;
      this.graph.on('node:dragstart', () => {
        canvas.set('localRefresh', false);
        this.graph.get('canvas').draw();
      });
      this.graph.on('node:drag', (e) => {
        if (throttleTimer) return;
        throttleTimer = setTimeout(() => {
          const model = e.item.get('model');
          const edges = this.graph.getEdges().filter(edge => {
            const source = edge.getSource();
            const target = edge.getTarget();
            return source.get('id') === model.id || target.get('id') === model.id;
          });
          edges.forEach(edge => {
            this.graph.refreshItem(edge);
          });
          throttleTimer = null;
        }, throttleInterval);
      });
      this.graph.on('node:dragend', (e) => {
        if (throttleTimer) {
          clearTimeout(throttleTimer);
          throttleTimer = null;
        }
        const model = e.item.get('model');
        const edges = this.graph.getEdges().filter(edge => {
          const source = edge.getSource();
          const target = edge.getTarget();
          return source.get('id') === model.id || target.get('id') === model.id;
        });
        edges.forEach(edge => {
          this.graph.refreshItem(edge);
        });
        canvas.set('localRefresh', true);
        this.graph.get('canvas').draw();
      });
      this.graph.data(this.graphData);
      this.graph.render();
      let debounceTimer = null;
      this.graph.on('afterchange', () => {
        if (debounceTimer) clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
          if (!canvas.get('destroyed')) {
            canvas.draw();
          }
        }, 16);
      });
    },
    initEvents() {
      // 监听窗口大小变化
      window.addEventListener('resize', this.handleResize);// 添加触摸事件处理
      const handleNodeClick = (evt) => {
        evt.preventDefault(); // 阻止默认触摸行为
        const node = evt.item;
        const nodeModel = node.getModel();
        // 如果节点已废弃,不允许任何操作
        if (!nodeModel.isDiscarded) {
          this.$message.warning('该节点已废弃,不能进行操作');
          return;
        }
        // 更新选中节点
        this.selectedNode = nodeModel;
        // 更新节点选中状态
        this.graphData.nodes.forEach(n => {
          n.selected = n.id === nodeModel.id;
        });
        this.graph.changeData(this.graphData);
      };
      this.graph.on('node:click', handleNodeClick);
      this.graph.on('node:touchstart', handleNodeClick);
      // 画布点击事件,取消选中节点(添加触摸支持)
      const handleCanvasClick = (evt) => {
        evt.preventDefault();
        this.selectedNode = null;
        this.graphData.nodes.forEach(n => {
          n.selected = false;
        });
        this.graph.changeData(this.graphData);
      };
      this.graph.on('canvas:click', handleCanvasClick);
      this.graph.on('canvas:touchstart', handleCanvasClick);
    },
    handleResize() {
      if (this.graph) {
        const container = document.getElementById('mountNode');
        const width = container.scrollWidth;
        const height = container.scrollHeight || 600;
        this.graph.changeSize(width, height);
      }
    },
    addNode() {
      // 如果没有节点,新增母代
      if (this.graphData.nodes.length === 0) {
        this.$refs.pedigreeForm.validate((valid) => {
          if (valid) {
            this.$refs.parentForm.openInitData({
              strainName: this.form.strainName,
              strainNo: this.form.strainNo,
              strainSourceStart: this.form.strainSourceStart,
              strainSourceEnd: this.form.strainSourceEnd,
            });
          }
        })
        return
      }
      // 如果选中了传代计划数节点,新增下一代
      if (this.selectedNode && this.selectedNode.label === '传代计划数') {
        const nodeModel = this.selectedNode;
        // 检查是否已达到计划数
        if (nodeModel.currentCount >= nodeModel.planCount) {
          this.$message.warning('已达到计划数,不能再添加');
          return;
        }
        // 获取父节点
        const parentEdge = this.graphData.edges.find(e => e.target === nodeModel.id);
        const parentNode = this.graphData.nodes.find(n => n.id === parentEdge.source);
        // 如果父节点是孙代,不允许添加
        if (parentNode.label === '孙代') {
          this.$message.warning('孙代节点不能再生成下一代');
          return;
        }
        const isParent = parentNode.label === '母代';
        const nextLevel = isParent ? '子代' : '孙代';
        this.showDiscarded = true;
        this.isAddingNode = true;
        this.$refs.addSublevelForm.openInitData({
          title: `新增${nextLevel}`,
          form: {
            strainName: this.form.strainName,
            strainNo: this.form.strainNo,
            isDiscarded: true
          }
        })
      } else {
        this.$message.warning('请选择传代计划数节点');
      }
    },
    handleAddParent(value) {
      console.log(value);
      const parentId = `parent-${++this.nodeCount}`;
      this.graphData.nodes.push({
        id: parentId,
        label: '母代',
        number: value.strainNo.trim(),
        data: value,
        isDiscarded: true,
        x: 200,
        y: 200,
        style: {
          fill: '#00B5AA',
        },
      });
      this.graph.changeData(this.graphData);
      this.$message.success('母代节点添加成功');
      this.$refs.parentForm.closeDialog();
    },
    handleDialogClose() {
      this.$refs.form.resetFields();
    },
    handleAddSublevel(value) {
      if (this.isAddingNode) {
        // 新增节点的处理逻辑
        const nodeModel = this.selectedNode;
        const parentEdge = this.graphData.edges.find(e => e.target === nodeModel.id);
        const parentNode = this.graphData.nodes.find(n => n.id === parentEdge.source);
        const isParent = parentNode.label === '母代';
        const nextLevel = isParent ? '子代' : '孙代';
        const childId = `child-${++this.nodeCount}`;
        this.graphData.nodes.push({
          id: childId,
          label: nextLevel,
          number: value.inoculateNo.trim(),
          isDiscarded: value.isDiscarded,
          data: value,
          style: {
            fill: value.isDiscarded ? '#999' : '#00B5AA',
            opacity: value.isDiscarded ? 0.3 : (isParent ? 0.6 : 0.4),
          },
        });
        this.graphData.edges.push({
          source: nodeModel.id,
          target: childId,
          style: {
            stroke: 'rgba(4, 156, 154, 1)',
            lineWidth: 1,
          },
        });
        const nodeIndex = this.graphData.nodes.findIndex(n => n.id === nodeModel.id);
        this.graphData.nodes[nodeIndex].currentCount++;
        this.graph.changeData(this.graphData);
        this.$message.success(`${nextLevel}添加成功`);
        this.$refs.addSublevelForm.closeDialog();
        this.isAddingNode = false;
      } else {
        // 编辑节点的处理逻辑
        const nodeModel = this.selectedNode;
        const nodeIndex = this.graphData.nodes.findIndex(n => n.id === nodeModel.id);
        if (nodeIndex > -1) {
          if (nodeModel.label === '传代计划数') {
            this.graphData.nodes[nodeIndex].planCount = parseInt(value.value);
          } else {
            this.graphData.nodes[nodeIndex].number = value.value.trim();
            if (this.showDiscarded) {
              this.graphData.nodes[nodeIndex].isDiscarded = value.isDiscarded;
              // 如果设置为废弃状态,同时废弃所有子节点
              if (value.isDiscarded) {
                const discardChildren = (parentId) => {
                  const childEdges = this.graphData.edges.filter(e => e.source === parentId);
                  childEdges.forEach(edge => {
                    const childNode = this.graphData.nodes.find(n => n.id === edge.target);
                    if (childNode) {
                      const childIndex = this.graphData.nodes.findIndex(n => n.id === childNode.id);
                      if (childIndex > -1) {
                        this.graphData.nodes[childIndex].isDiscarded = true;
                        this.graphData.nodes[childIndex].style.fill = '#999';
                        this.graphData.nodes[childIndex].style.opacity = 0.3;
                        // 递归处理子节点的子节点
                        discardChildren(childNode.id);
                      }
                    }
                  });
                };
                discardChildren(nodeModel.id);
              }
            }
          }
          this.graph.changeData(this.graphData);
          this.$message.success('修改成功');
          this.dialogVisible = false;
        }
      }
    },
    setGenerationPlan() {
      if (!this.selectedNode) {
        this.$message.warning('请先选择节点');
        return;
      }
      const nodeModel = this.selectedNode;
      if (nodeModel.label === '孙代') {
        this.$message.warning('孙代节点不能再生成传代计划数');
        return;
      }
      if (nodeModel.label === '传代计划数') {
        this.$message.warning('传代计划数节点不能再设置计划数');
        return;
      }
      const hasGenerationNode = this.graphData.edges.some(e =>
        e.source === nodeModel.id &&
        this.graphData.nodes.some(n => n.id === e.target && n.label === '传代计划数')
      );
      if (hasGenerationNode) {
        this.$message.warning('该节点已经存在传代计划数节点');
        return;
      }
      if (nodeModel.label === '子代') {
        this.$refs.addSublevelPlan.openInitData({
          ...nodeModel.data,
          label: nodeModel.label,
          strainName: this.form.strainName,
          strainNo: this.form.strainNo,
          strainSourceStart: this.form.strainSourceStart,
          strainSourceEnd: this.form.strainSourceEnd,
        })
      } else {
        this.$refs.planForm.openInitData({
          ...nodeModel.data,
          label: nodeModel.label,
          strainName: this.form.strainName,
          strainNo: this.form.strainNo,
          strainSourceStart: this.form.strainSourceStart,
          strainSourceEnd: this.form.strainSourceEnd,
        })
      }
    },
    handleAddPlan(value) {
      const nodeModel = this.selectedNode;
      const generationId = `generation-${++this.nodeCount}`;
      this.graphData.nodes.push({
        id: generationId,
        label: '传代计划数',
        planCount: value.count,
        data: value,
        isDiscarded: true,
        currentCount: 0,
        style: {
          fill: '#00B5AA',
        },
      });
      this.graphData.edges.push({
        source: nodeModel.id,
        target: generationId,
        style: {
          stroke: 'rgba(4, 156, 154, 1)',
          lineWidth: 1,
        },
      });
      this.graph.changeData(this.graphData);
      this.$message.success('传代计划数设置成功');
      this.$refs.planForm.closeDialog()
    },
    showDetail() {
      if (!this.selectedNode) {
        this.$message.warning('请先选择节点');
        return;
      }
      const nodeModel = this.selectedNode;
      if (nodeModel.label === '母代') {
        this.$refs.parentForm.openInitData({ ...nodeModel.data, status: 'detail' });
      } else if (nodeModel.label === '子代' || nodeModel.label === '孙代') {
        this.dialogTitle = `${nodeModel.label}详情`;
        this.$refs.addSublevelForm.openInitData({
          title: `${nodeModel.label}详情`,
          form: { ...nodeModel.data }
        })
      } else if (nodeModel.label === '传代计划数') {
        const nodeIndex = this.graphData.nodes.findIndex(n => n.id === nodeModel.id);
        if (this.graphData.nodes[nodeIndex - 1].label === '子代') {
          this.$refs.addSublevelPlan.openInitData({ ...nodeModel.data, status: 'detail' });
        } else {
          this.$refs.planForm.openInitData({ ...nodeModel.data, status: 'detail' });
        }
      }
    }
  },
};
</script>
@@ -135,26 +752,31 @@
  display: flex;
  align-items: center;
}
.chart {
  padding: 20px 38px;
  background: rgba(255,255,255,0.8);
  box-shadow: 0px 10px 19px 0px rgba(0,0,0,0.06);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: 0px 10px 19px 0px rgba(0, 0, 0, 0.06);
  border-radius: 16px;
  border: 4px solid #FFFFFF;
  margin-top: 30px;
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .title {
        font-size: 18px;
      font-size: 18px;
    }
    .option-btn {
        display: flex;
        gap: 10px;
        .el-button {
          margin-left: 0;
        }
      display: flex;
      gap: 10px;
      .el-button {
        margin-left: 0;
      }
    }
  }
}
@@ -253,4 +875,28 @@
  flex-wrap: wrap;
  gap: 10px;
}
</style>
.strain-flow-chart {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .toolbar {
    margin-bottom: 16px;
    display: flex;
    gap: 12px;
    .el-button {
      margin-right: 0;
    }
  }
  #mountNode {
    flex: 1;
    width: 100%;
    min-height: 500px;
    border-radius: 4px;
  }
}
</style>