| | |
| | | <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="菌种源" 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-input v-model="form.strainSourceStart" placeholder="请输入" :disabled="!!$route.query.id" |
| | | 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-input v-model="form.strainSourceEnd" placeholder="请输入" :disabled="!!$route.query.id" |
| | | class="fixed-width-input"></el-input> |
| | | </el-form-item> |
| | | </div> |
| | | <span class="form-text">细胞库</span> |
| | | </div> |
| | | </el-form-item> |
| | | <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" placeholder="请输入" :disabled="!!$route.query.id" |
| | | 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"> |
| | | <Table :height="null" :total="0" :tableData="tableData"> |
| | | <el-table-column label="接种操作人" prop="strainSource" /> |
| | | <el-table-column label="接种操作时间" prop="strainCode" /> |
| | | <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="操作"> |
| | | <div class="card" v-if="roleType != 4" style="margin-top: 30px; display: block"> |
| | | <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">确认入库</el-button> |
| | | <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="保存/废弃"> |
| | | <template #default="{ row }"> |
| | | {{ row.status === 1 ? "保存" : "废弃" }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="菌种入库时间/菌种废弃时间" prop="createTime" /> |
| | | <el-table-column v-if="roleType == 2" label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleConfirm(row)">确认入库</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | |
| | | <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" v-if="!isReadOnly && (roleType == 3 || roleType == 1)" class="el-icon-plus" @click="addNode" :disabled="editBoolean"> |
| | | 新增</el-button> |
| | | |
| | | <el-button type="primary" v-if="!isReadOnly && (roleType == 3 || roleType == 1)" |
| | | @click="setGenerationPlan" :disabled="editBoolean">设置传代计划数</el-button> |
| | | <el-button type="primary" @click="showDetail">详情</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 type="primary" @click="handleSubmit" style="width: 150px" |
| | | >保存</el-button |
| | | > |
| | | <!-- v-if="!$route.query.id || (roleType == 1 && $route.query.id)" --> |
| | | <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> |
| | | <div class="end-btn"> |
| | | <!-- <el-button @click="handleDraft">存草稿</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" |
| | | /> |
| | | <ParentForm :key="pageInstanceKey" ref="parentForm" @addNodeSign="addNodeSign" /> |
| | | <PlanForm :key="pageInstanceKey" ref="planForm" @addNodeSign="addNodeSign" /> |
| | | <AddSublevelForm :key="pageInstanceKey" ref="addSublevelForm" @addNodeSign="addNodeSign" /> |
| | | <AddSublevelPlan :key="pageInstanceKey" ref="addSublevelPlan" @addNodeSign="addNodeSign" /> |
| | | <ConfirmStorageDialog :key="`signature-${pageInstanceKey}`" name="接种操作人签字" :visible.sync="confirmStorageDialogVisible" |
| | | @confirm="handleSignatureConfirm" /> |
| | | <!-- 菌种工程师 --> |
| | | <ConfirmStorageDialog |
| | | name="菌种保藏人签字" |
| | | text="是否确认该项菌种信息入库" |
| | | :visible.sync="storageVisible" |
| | | @confirm="handleSignatureConfirm" |
| | | /> |
| | | <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> |
| | | |
| | |
| | | import AddSublevelForm from "./components/AddSublevelForm.vue"; |
| | | import AddSublevelPlan from "./components/AddSublevelPlan.vue"; |
| | | import ConfirmStorageDialog from "@/components/confirm-storage-dialog"; |
| | | import { add } from './service' |
| | | import ApprovalCount from "./progenitorComponents/approvalCount.vue"; |
| | | import { |
| | | add, |
| | | getDetail, |
| | | addCount, |
| | | addProgenitorChild, |
| | | addProgenitor, |
| | | pageListDetail, |
| | | confirmStorage, |
| | | deleteNode, |
| | | updateChild, |
| | | edit, |
| | | confirmCount, |
| | | pageListCountDetail |
| | | } from "./service"; |
| | | import ChooseProject from "@/components/chooseProject/index.vue"; |
| | | export default { |
| | | name: "AddPedigree", |
| | | components: { |
| | | ChooseProject, |
| | | ParentForm, |
| | | PlanForm, |
| | | AddSublevelForm, |
| | | AddSublevelPlan, |
| | | ConfirmStorageDialog, |
| | | ApprovalCount, |
| | | }, |
| | | data() { |
| | | return { |
| | | showChoose: false, |
| | | projectData: [], // 存储选中的项目组数据 |
| | | queryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1, |
| | | }, |
| | | signatureVisible: false, |
| | | form: { |
| | | strainSourceStart: "", |
| | |
| | | nodeData: {}, |
| | | nodeType: "", //1母代 2计划数 3子孙代 |
| | | tableData: [], |
| | | cacheData: null, // 👈 添加这一行 |
| | | activeRouteKey: "", |
| | | graphLoadId: 0, |
| | | pageInstanceKey: 0, |
| | | confirmStorageDialogVisible: false, |
| | | storageVisible: false, |
| | | editBoolean: false, |
| | | treeData: [], |
| | | total: 0, |
| | | roleType: JSON.parse(sessionStorage.getItem("userInfo")).roleType || 1, // 1.超级管理员 2.审批人 3.工程师 4.实验员 |
| | | |
| | | // 新增2.0 |
| | | nodeTreeStatus: 1, //1.未提交 2.已提交 |
| | | newTotal: 0, |
| | | newCurrent: 1, |
| | | newSize: 10, |
| | | newTableData: [], |
| | | newQueryForm: { |
| | | pageSize: 10, |
| | | pageNum: 1, |
| | | }, |
| | | }; |
| | | }, |
| | | computed: { |
| | | isReadOnly() { |
| | | return this.$route.path.includes('detail') || this.$route.query.mode === 'detail'; |
| | | }, |
| | | canAddNode() { |
| | | // 如果没有节点,可以新增母代 |
| | | if (this.graphData.nodes.length === 0) { |
| | |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.initGraph(); |
| | | this.initEvents(); |
| | | this.resetMountNode(); |
| | | }, |
| | | deactivated() { |
| | | // 缓存数据 |
| | | this.cacheData = { |
| | | form: JSON.parse(JSON.stringify(this.form)), |
| | | graphData: JSON.parse(JSON.stringify(this.graphData)), |
| | | nodeCount: this.nodeCount, |
| | | selectedNode: this.selectedNode ? JSON.parse(JSON.stringify(this.selectedNode)) : null, |
| | | tableData: JSON.parse(JSON.stringify(this.tableData)), |
| | | newTableData: JSON.parse(JSON.stringify(this.newTableData)), |
| | | total: this.total, |
| | | newTotal: this.newTotal, |
| | | projectData: JSON.parse(JSON.stringify(this.projectData)), |
| | | treeData: JSON.parse(JSON.stringify(this.treeData)), |
| | | nodeTreeStatus: this.nodeTreeStatus, |
| | | routeKey: this.activeRouteKey |
| | | }; |
| | | }, |
| | | activated() { |
| | | if (this.cacheData && this.cacheData.routeKey === this.$route.fullPath) { |
| | | // 恢复数据 |
| | | this.form = JSON.parse(JSON.stringify(this.cacheData.form)); |
| | | this.graphData = JSON.parse(JSON.stringify(this.cacheData.graphData)); |
| | | this.nodeCount = this.cacheData.nodeCount; |
| | | this.selectedNode = this.cacheData.selectedNode; |
| | | this.tableData = this.cacheData.tableData || []; |
| | | this.newTableData = this.cacheData.newTableData || []; |
| | | this.total = this.cacheData.total || 0; |
| | | this.newTotal = this.cacheData.newTotal || 0; |
| | | this.projectData = this.cacheData.projectData || []; |
| | | this.treeData = this.cacheData.treeData || []; |
| | | this.nodeTreeStatus = this.cacheData.nodeTreeStatus || 1; |
| | | |
| | | // 更新图表 |
| | | this.resetMountNode(); |
| | | if (this.graphData.nodes.length > 0) { |
| | | this.updateGraphData(); |
| | | } |
| | | return; |
| | | } |
| | | this.cacheData = null; |
| | | if (this.$route.query.id) { |
| | | this.reloadData(); |
| | | } else { |
| | | this.resetPageState(); |
| | | } |
| | | if (this.$route.query.status !== undefined && this.$route.query.status != 1 && this.roleType != 1){ |
| | | this.editBoolean = true |
| | | }else { |
| | | this.editBoolean = false |
| | | } |
| | | }, |
| | | watch: { |
| | | '$route': { |
| | | immediate: true, |
| | | handler(to) { |
| | | if (!["AddPedigree", "DetailPedigree"].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.cacheData = null; |
| | | this.resetPageState(); |
| | | } |
| | | if (to.query.id) { |
| | | this.reloadData(); |
| | | } |
| | | |
| | | this.editBoolean = this.shouldDisableEditing(to.query); |
| | | } |
| | | } |
| | | }, |
| | | 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 = { |
| | | strainSourceStart: "", |
| | | strainSourceEnd: "", |
| | | cellBank: "", |
| | | strainCode: "", |
| | | strainName: "", |
| | | remarks: "", |
| | | }; |
| | | 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.nodeTreeStatus = 1; |
| | | this.editBoolean = this.shouldDisableEditing(); |
| | | this.resetGraphData(); |
| | | this.$nextTick(() => { |
| | | this.$refs.pedigreeForm && this.$refs.pedigreeForm.clearValidate(); |
| | | }); |
| | | }, |
| | | resetGraphData() { |
| | | this.graphLoadId += 1; |
| | | this.graphData = { |
| | | nodes: [], |
| | | edges: [], |
| | | }; |
| | | this.treeData = []; |
| | | 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; |
| | | }, |
| | | handleEdit() { |
| | | 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.parentForm.openInitData({ |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | ...nodeModel.data, |
| | | formStatus: "edit", |
| | | }); |
| | | } else if (nodeModel.label === "子代" || nodeModel.label === "孙代") { |
| | | this.dialogTitle = `${nodeModel.label}详情`; |
| | | this.$refs.addSublevelForm.openInitData({ |
| | | strainCode1: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | title: `编辑${nodeModel.label}`, |
| | | form: { ...nodeModel.data }, |
| | | formStatus: "edit", |
| | | }); |
| | | } else if (nodeModel.label === "传代计划数") { |
| | | const nodeIndex = this.graphData.nodes.findIndex( |
| | | (n) => n.nodeId === nodeModel.nodeId |
| | | ); |
| | | if (this.graphData.nodes[nodeIndex - 1].label === "子代") { |
| | | this.$refs.addSublevelPlan.openInitData({ |
| | | ...nodeModel.data, |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainCode1: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | confirmTime: this.form.confirmTime, |
| | | parentId: nodeModel.id, |
| | | generationCount: nodeModel.data.generationCount || nodeModel.planCount, |
| | | formStatus: "edit", |
| | | }); |
| | | } else { |
| | | this.$refs.planForm.openInitData({ |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | strainCode1: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | ...nodeModel.data, |
| | | generationCount: nodeModel.data.generationCount || nodeModel.planCount, |
| | | formStatus: "edit", |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | handleDelete() { |
| | | 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(() => { |
| | | // 判断是新增模式还是编辑模式 |
| | | if (!this.$route.query.id) { |
| | | // 新增模式:前端直接删除节点 |
| | | this.deleteNodeFromGraph(this.selectedNode.nodeId); |
| | | this.$message.success("删除成功"); |
| | | } else { |
| | | // 编辑模式:调用后端删除接口 |
| | | deleteNode({ id: this.selectedNode.id }).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("删除成功"); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 前端删除节点方法 |
| | | deleteNodeFromGraph(nodeId) { |
| | | // 找到要删除的节点 |
| | | const nodeIndex = this.graphData.nodes.findIndex(n => n.nodeId === nodeId); |
| | | if (nodeIndex === -1) { |
| | | return; |
| | | } |
| | | |
| | | // 递归收集所有需要删除的节点ID(包括子节点) |
| | | const collectNodeIds = (currentNodeId) => { |
| | | const nodeIds = [currentNodeId]; |
| | | const childEdges = this.graphData.edges.filter(e => e.source === currentNodeId); |
| | | childEdges.forEach(edge => { |
| | | nodeIds.push(...collectNodeIds(edge.target)); |
| | | }); |
| | | return nodeIds; |
| | | }; |
| | | |
| | | const nodeIdsToDelete = collectNodeIds(nodeId); |
| | | |
| | | // 删除所有相关的边 |
| | | this.graphData.edges = this.graphData.edges.filter(edge => { |
| | | return !nodeIdsToDelete.includes(edge.source) && !nodeIdsToDelete.includes(edge.target); |
| | | }); |
| | | |
| | | // 删除所有相关的节点 |
| | | this.graphData.nodes = this.graphData.nodes.filter(node => { |
| | | return !nodeIdsToDelete.includes(node.nodeId); |
| | | }); |
| | | |
| | | // 如果删除的节点的父节点是传代计划数,需要更新其当前数量 |
| | | const parentEdge = this.graphData.edges.find(e => e.target === nodeId); |
| | | if (parentEdge) { |
| | | const parentNode = this.graphData.nodes.find(n => n.nodeId === parentEdge.source); |
| | | if (parentNode && parentNode.label === '传代计划数') { |
| | | // 重新计算当前数量 |
| | | const childCount = this.graphData.edges.filter(e => e.source === parentNode.nodeId).length; |
| | | parentNode.currentCount = childCount; |
| | | } |
| | | } |
| | | |
| | | // 清空选中节点 |
| | | this.selectedNode = null; |
| | | |
| | | // 更新图表显示 |
| | | this.updateGraphData(); |
| | | }, |
| | | handleConfirm(row) { |
| | | this.comfirmId = row.id; |
| | | this.storageVisible = true; |
| | | }, |
| | | handleSignatureConfirm1(signatureImage) { |
| | | confirmStorage({ |
| | | id: this.comfirmId, |
| | | preserveSignature: signatureImage.signature, |
| | | }).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("确认入库成功"); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | }, |
| | | // 处理每页显示数量变化 |
| | | handleSizeChange(val) { |
| | | this.size = val; |
| | | this.queryForm.pageSize = val; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // 处理页码变化 |
| | | handleCurrentChange(val) { |
| | | this.current = val; |
| | | this.queryForm.pageNum = val; |
| | | this.getList(); |
| | | }, |
| | | async getList() { |
| | | try { |
| | | // 获取列表数据 |
| | | const listRes = await pageListDetail({ |
| | | id: this.$route.query.id, |
| | | current: this.current, |
| | | size: this.size, |
| | | }); |
| | | |
| | | if (listRes.code === 200) { |
| | | this.tableData = listRes.data.records; |
| | | this.total = listRes.data.total; |
| | | this.current = listRes.data.current; |
| | | this.size = listRes.data.size; |
| | | } |
| | | |
| | | // ... 其他现有的 reloadData 代码 ... |
| | | } catch (error) { |
| | | console.error("Failed to reload data:", error); |
| | | 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("数据加载失败"); |
| | | } |
| | | }, |
| | | reloadData() { |
| | | this.resetPageState(); |
| | | this.resetMountNode(); |
| | | const graphLoadId = this.graphLoadId; |
| | | const routeKey = this.$route.fullPath; |
| | | this.getList(); |
| | | this.getNewList() |
| | | if (!this.$route.query.id) { |
| | | return |
| | | } |
| | | getDetail({ id: this.$route.query.id }).then((res) => { |
| | | if (graphLoadId !== this.graphLoadId || routeKey !== this.$route.fullPath) { |
| | | return; |
| | | } |
| | | const nodeMap = new Map(); |
| | | const calculateLevel = (node) => { |
| | | if (node.parentId === "0") return 0; |
| | | const parent = nodeMap.get(node.parentId); |
| | | if (!parent) return 0; |
| | | return calculateLevel(parent) + 1; |
| | | }; |
| | | |
| | | // 首先创建所有节点的映射 |
| | | const createNodeMap = (nodes) => { |
| | | nodes.forEach((node) => { |
| | | nodeMap.set(node.id, node); |
| | | if (node.children) { |
| | | createNodeMap(node.children); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const processNode = (node) => { |
| | | const nodeId = node.id; // 直接使用后端返回的id |
| | | const level = calculateLevel(node); |
| | | let label = ""; |
| | | |
| | | if (level === 0) { |
| | | label = "母代"; |
| | | } else if (level === 1) { |
| | | label = node.generationCount !== null ? "传代计划数" : "子代"; |
| | | } else if (level === 2) { |
| | | label = "子代"; |
| | | } else if (level === 3) { |
| | | label = node.generationCount !== null ? "传代计划数" : "孙代"; |
| | | } else if (level === 4) { |
| | | label = "孙代"; |
| | | } |
| | | |
| | | return { |
| | | nodeId, |
| | | label, |
| | | number: node.strainCode, |
| | | data: node, |
| | | status: node.status, |
| | | planCount: node.generationCount, |
| | | currentCount: 0, |
| | | style: { |
| | | fill: node.status === 1 ? "#00B5AA" : "#999", |
| | | opacity: |
| | | node.status === 1 |
| | | ? level === 0 |
| | | ? 1 |
| | | : level === 1 |
| | | ? 0.6 |
| | | : 0.4 |
| | | : 0.3, |
| | | }, |
| | | }; |
| | | }; |
| | | |
| | | // 重置数据 |
| | | this.graphData.nodes = []; |
| | | this.graphData.edges = []; |
| | | |
| | | if ( |
| | | res.pedigreeChartParentAllDetailDTO && |
| | | res.pedigreeChartParentAllDetailDTO.one |
| | | ) { |
| | | // 创建节点映射 |
| | | createNodeMap(res.pedigreeChartParentAllDetailDTO.one); |
| | | |
| | | // 处理所有节点 |
| | | const processAllNodes = (nodes) => { |
| | | nodes.forEach((node) => { |
| | | if (Number(this.roleType) === 2 || node.codeStatus == 2 || (node.codeStatus == 1 && Number(this.roleType) === 3)) { |
| | | const processedNode = processNode(node); |
| | | this.graphData.nodes.push(processedNode); |
| | | |
| | | // 根据parentId创建边,直接使用原始id |
| | | if (node.parentId !== "0") { |
| | | this.graphData.edges.push({ |
| | | source: node.parentId, |
| | | target: node.id, |
| | | style: { |
| | | stroke: "rgba(4, 156, 154, 1)", |
| | | lineWidth: 1, |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | if (node.children) { |
| | | processAllNodes(node.children); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 处理所有节点 |
| | | processAllNodes(res.pedigreeChartParentAllDetailDTO.one); |
| | | } |
| | | |
| | | this.form = { |
| | | strainSourceStart: res.strainSourceStart, |
| | | strainSourceEnd: res.strainSourceEnd, |
| | | strainCode: res.strainCode, |
| | | strainName: res.strainName, |
| | | }; |
| | | this.nodeTreeStatus = res.status |
| | | |
| | | this.projectData = res.tprojectTeamList |
| | | |
| | | // 更新图表 |
| | | this.updateGraphData(); |
| | | this.cacheData = null; |
| | | }); |
| | | }, |
| | | addNodeSign(value, type) { |
| | | this.nodeData = value; |
| | | this.nodeType = type; |
| | | // this.$refs.addAncestor.closeDialog() |
| | | // this.$refs.addSublevelForm.close() |
| | | 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) { |
| | | if (this.treeData.length == 0) { |
| | | if (this.treeData.length === 0) { |
| | | this.$message.warning("请新增节点"); |
| | | return; |
| | | } |
| | | |
| | | // 处理节点数据,将data字段中的数据提升到根级别 |
| | | const processNodeData = (node) => { |
| | | const processNodeData = (node, type) => { |
| | | console.log('node.codeStatus',node) |
| | | const processedNode = { |
| | | ...node, |
| | | ...node.data, |
| | | codeStatus: type == 2 ? '2' : node.data.codeStatus || type, |
| | | children: [], |
| | | }; |
| | | delete processedNode.data; |
| | | return processedNode; |
| | | }; |
| | | |
| | | // 将扁平结构转换为嵌套结构 |
| | | const buildNestedStructure = (nodes) => { |
| | | const levelMap = { |
| | | 0: 'one', |
| | | 1: 'two', |
| | | 2: 'three', |
| | | 3: 'four', |
| | | 4: 'five' |
| | | }; |
| | | // 构建 children 树结构 |
| | | const buildTree = (nodes, edges) => { |
| | | // 创建节点映射,提升性能 |
| | | const nodeMap = new Map( |
| | | nodes.map((node) => [node.nodeId, processNodeData(node, type)]) |
| | | ); |
| | | |
| | | // 处理每个节点 |
| | | const processedNodes = nodes.map(node => { |
| | | const processedNode = processNodeData(node); |
| | | // 设置 type 字段 |
| | | if (node.level % 2 === 0) { // 0, 2, 4 对应 one, three, five |
| | | processedNode.type = 1; |
| | | } else { // 1, 3 对应 two, four |
| | | processedNode.type = 2; |
| | | } |
| | | return processedNode; |
| | | }); |
| | | // 创建子节点ID集合,用于快速查找根节点 |
| | | const childNodeIds = new Set(edges.map((edge) => edge.target)); |
| | | |
| | | // 构建嵌套结构 |
| | | const result = {}; |
| | | const nodeMap = new Map(); |
| | | |
| | | // 首先创建所有节点的映射 |
| | | processedNodes.forEach(node => { |
| | | nodeMap.set(node.nodeId, { ...node }); |
| | | }); |
| | | |
| | | // 处理边关系,构建嵌套结构 |
| | | this.graphData.edges.forEach(edge => { |
| | | // 构建父子关系 |
| | | edges.forEach((edge) => { |
| | | const parent = nodeMap.get(edge.source); |
| | | const child = nodeMap.get(edge.target); |
| | | if (parent && child) { |
| | | const parentLevel = parent.level; |
| | | const childLevel = child.level; |
| | | const parentKey = levelMap[parentLevel]; |
| | | const childKey = levelMap[childLevel]; |
| | | |
| | | // 确保父节点存在 |
| | | if (!result[parentKey]) { |
| | | result[parentKey] = { ...parent }; |
| | | } |
| | | |
| | | // 根据层级关系设置子节点 |
| | | if (parentLevel === 0) { // one 包含 two |
| | | if (!result[parentKey].two) { |
| | | result[parentKey].two = []; |
| | | } |
| | | result[parentKey].two.push(child); |
| | | } else if (parentLevel === 1) { // two 包含 three |
| | | if (!result.one.two) { |
| | | result.one.two = []; |
| | | } |
| | | const twoNode = result.one.two.find(n => n.nodeId === parent.nodeId); |
| | | if (twoNode) { |
| | | if (!twoNode.three) { |
| | | twoNode.three = []; |
| | | } |
| | | twoNode.three.push(child); |
| | | } |
| | | } else if (parentLevel === 2) { // three 包含 four |
| | | result.one.two.forEach(twoNode => { |
| | | if (twoNode.three) { |
| | | const threeNode = twoNode.three.find(n => n.nodeId === parent.nodeId); |
| | | if (threeNode) { |
| | | if (!threeNode.four) { |
| | | threeNode.four = []; |
| | | } |
| | | threeNode.four.push(child); |
| | | } |
| | | } |
| | | }); |
| | | } else if (parentLevel === 3) { // four 包含 five |
| | | result.one.two.forEach(twoNode => { |
| | | if (twoNode.three) { |
| | | twoNode.three.forEach(threeNode => { |
| | | if (threeNode.four) { |
| | | const fourNode = threeNode.four.find(n => n.nodeId === parent.nodeId); |
| | | if (fourNode) { |
| | | if (!fourNode.five) { |
| | | fourNode.five = []; |
| | | } |
| | | fourNode.five.push(child); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | child.level = parent.level + 1; |
| | | parent.children.push(child); |
| | | } |
| | | }); |
| | | |
| | | // 如果没有边关系,至少保留第一层节点 |
| | | if (Object.keys(result).length === 0 && processedNodes.length > 0) { |
| | | const rootNode = processedNodes.find(node => node.level === 0); |
| | | if (rootNode) { |
| | | result.one = { ...rootNode }; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | // 返回根节点数组 |
| | | return nodes |
| | | .filter((node) => !childNodeIds.has(node.nodeId)) |
| | | .map((node) => nodeMap.get(node.nodeId)); |
| | | }; |
| | | |
| | | // 获取基础表单数据 |
| | | const baseData = { |
| | | let baseData = { |
| | | parent: { |
| | | generationType: 1, |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | strainCode: this.form.strainCode, |
| | | strainName: this.form.strainName, |
| | | status: type, |
| | | }, |
| | | ...(this.treeData.length > 0 ? buildNestedStructure(this.treeData) : {}) |
| | | one: buildTree(this.graphData.nodes, this.graphData.edges), |
| | | }; |
| | | console.log('这是提交数据', baseData) |
| | | if (this.$route.query.id) { |
| | | baseData.parent.id = this.$route.query.id; |
| | | |
| | | console.log("提交的数据:", baseData); |
| | | return |
| | | edit({ ...baseData }).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("编辑成功"); |
| | | this.cacheData = null; // 👈 添加这一行 |
| | | this.$closeCurrentView('/strain/pedigree-vhart'); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | add(baseData).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("保存成功"); |
| | | this.$router.back(); |
| | | this.cacheData = null; |
| | | this.$closeCurrentView('/strain/pedigree-vhart'); |
| | | } |
| | | }); |
| | | } |
| | |
| | | }, |
| | | handleDraft() { |
| | | // 实现存草稿逻辑 |
| | | console.log("save draft", this.form); |
| | | }, |
| | | handleCancel() { |
| | | this.$router.back(); |
| | | this.$closeCurrentView('/strain/pedigree-vhart'); |
| | | }, |
| | | handleSignatureConfirm(signatureImage) { |
| | | this.confirmStorageDialogVisible = false; |
| | | console.log(this.nodeType); |
| | | |
| | | if (this.nodeType === 1) { |
| | | this.handleAddParent({ |
| | | ...this.nodeData, |
| | | preserveSignature: signatureImage.signature, |
| | | type: this.nodeType == 2 ? 2 : 1, |
| | | vaccinateSignature: signatureImage.signature, |
| | | }); |
| | | } else if (this.nodeType === 2) { |
| | | this.handleAddPlan({ |
| | | ...this.nodeData, |
| | | preserveSignature: signatureImage.signature, |
| | | type: this.nodeType == 2 ? 2 : 1, |
| | | vaccinateSignature: signatureImage.signature, |
| | | }); |
| | | } else if (this.nodeType === 3) { |
| | | this.handleAddSublevel({ |
| | | ...this.nodeData, |
| | | preserveSignature: signatureImage.signature, |
| | | type: this.nodeType == 2 ? 2 : 1, |
| | | vaccinateSignature: signatureImage.signature, |
| | | }); |
| | | this.$refs.addSublevelPlan.closeDialog(); |
| | | } |
| | | // 处理提交逻辑 |
| | | }, |
| | | initGraph() { |
| | | const container = document.getElementById("mountNode"); |
| | | const container = this.$refs.mountNode; |
| | | if (!container) return; |
| | | const width = container.scrollWidth; |
| | | const height = container.scrollHeight || 600; |
| | | |
| | |
| | | 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", { |
| | |
| | | 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", |
| | |
| | | if (cfg.label === "传代计划数") { |
| | | content = `${cfg.planCount || 0}`; |
| | | } else if (cfg.number) { |
| | | content = |
| | | cfg.label === "母代" |
| | | ? `代传菌种编号:${cfg.number}` |
| | | : `接种菌种编号:${cfg.number}`; |
| | | console.log("qweqweqweqw", cfg.data); |
| | | |
| | | // 获取类型名称 |
| | | let typeName = "传代菌种"; |
| | | // if (cfg.data && cfg.data.strainType) { |
| | | // const typeMap = { |
| | | // "1": "原始祖代菌株SO", |
| | | // "2": "分离菌落 CO", |
| | | // "3": "祖代菌株 O", |
| | | // }; |
| | | // typeName = typeMap[cfg.data.strainType] || "接种菌种"; |
| | | // } |
| | | |
| | | if (cfg.data.parentId) { |
| | | typeName = "接代菌种"; |
| | | } |
| | | |
| | | content = `${typeName}编号:${cfg.number}`; |
| | | } |
| | | |
| | | if (content) { |
| | |
| | | x: 0, |
| | | y: -totalHeight / 2 + titleHeight + gap + contentHeight / 2, |
| | | fill: textFill, |
| | | fontSize: 10, |
| | | fontSize: 12, |
| | | textAlign: "center", |
| | | textBaseline: "middle", |
| | | cursor: "move", |
| | |
| | | }); |
| | | |
| | | this.graph = new G6.Graph({ |
| | | container: "mountNode", |
| | | container, |
| | | width, |
| | | height, |
| | | fitView: true, |
| | |
| | | nodeMap.set(node.nodeId, { |
| | | ...node, |
| | | id: node.nodeId, |
| | | level: 0 // 添加层级标记 |
| | | level: 0, // 添加层级标记 |
| | | children: [], // 添加children数组 |
| | | }); |
| | | }); |
| | | |
| | |
| | | if (parent && child) { |
| | | // 设置子节点的层级 |
| | | child.level = parent.level + 1; |
| | | // 将子节点添加到父节点的children数组中 |
| | | parent.children.push(child); |
| | | } |
| | | }); |
| | | |
| | |
| | | } |
| | | }); |
| | | |
| | | // 将所有节点按层级排序 |
| | | // 将所有节点按层级排序并设置type字段 |
| | | const allNodes = Array.from(nodeMap.values()); |
| | | allNodes.sort((a, b) => a.level - b.level); |
| | | allNodes.sort((a, b) => { |
| | | // 首先按层级排序 |
| | | if (a.level !== b.level) { |
| | | return a.level - b.level; |
| | | } |
| | | // 如果层级相同,按节点ID排序以保持稳定 |
| | | return a.nodeId.localeCompare(b.nodeId); |
| | | }); |
| | | |
| | | // 设置type字段:第1,3,5层为1,其他层级为2 |
| | | allNodes.forEach((node) => { |
| | | node.type = [1, 3, 5].includes(node.level + 1) ? 1 : 2; |
| | | }); |
| | | |
| | | return allNodes; |
| | | }; |
| | | |
| | | const treeData = buildTree(this.graphData.nodes, this.graphData.edges); |
| | | |
| | | // 更新图表数据 |
| | | this.graph.changeData({ |
| | | // 更新图表数据,确保边的连接关系正确 |
| | | const processedData = { |
| | | nodes: this.graphData.nodes.map((node) => ({ |
| | | ...node, |
| | | id: node.nodeId, |
| | |
| | | edges: this.graphData.edges.map((edge) => ({ |
| | | ...edge, |
| | | id: `${edge.source}-${edge.target}`, |
| | | // 确保边的样式一致 |
| | | 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)", |
| | | }, |
| | | }, |
| | | })), |
| | | }); |
| | | }; |
| | | |
| | | // 更新图表数据 |
| | | this.graph.changeData(processedData); |
| | | |
| | | // 保存树形结构数据 |
| | | this.treeData = treeData; |
| | |
| | | }, |
| | | 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); |
| | | } |
| | | }, |
| | | addNode() { |
| | | // 如果没有节点,新增祖代 |
| | | console.log("选择的节点", this.selectedNode); |
| | | if ( |
| | | this.selectedNode && |
| | | this.selectedNode.data && |
| | | this.selectedNode.data.auditStatus !== undefined && |
| | | this.selectedNode.data.auditStatus != 2 |
| | | ) { |
| | | this.$message.warning("该传代计划数未审核,请先审核"); |
| | | return; |
| | | } |
| | | |
| | | // 如果没有节点,新增母代 |
| | | if (this.graphData.nodes.length === 0) { |
| | | this.$refs.pedigreeForm.validate((valid) => { |
| | |
| | | strainCode: this.form.strainCode, |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | formStatus: "add", |
| | | }); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | // |
| | | if ( |
| | | !this.$route.query.id && |
| | | this.selectedNode && |
| | | this.selectedNode.label === "传代计划数" |
| | | ) { |
| | | this.$message.warning("一次只能添加一个传代"); |
| | | return; |
| | | } |
| | | |
| | |
| | | this.showDiscarded = true; |
| | | this.isAddingNode = true; |
| | | this.$refs.addSublevelForm.openInitData({ |
| | | parentId: nodeModel.id, |
| | | title: `新增${nextLevel}`, |
| | | strainName1: this.form.strainName, |
| | | strainCode1: this.form.strainCode, |
| | | form: { |
| | | strainName: this.form.strainName, |
| | | strainCode: this.form.strainCode, |
| | | isDiscarded: true, |
| | | }, |
| | | }); |
| | |
| | | } |
| | | }, |
| | | handleAddParent(value) { |
| | | console.log(value); |
| | | |
| | | if (this.$route.query.id) { |
| | | value.pedigreeChartId = this.$route.query.id; |
| | | value.parentId = "0"; |
| | | addProgenitor(value).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("操作成功"); |
| | | this.$refs.parentForm.closeDialog(); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | const parentId = `parent-${++this.nodeCount}`; |
| | | this.graphData.nodes.push({ |
| | | nodeId: parentId, |
| | |
| | | this.$refs.form.resetFields(); |
| | | }, |
| | | handleAddSublevel(value) { |
| | | console.log('11111111111111111', value) |
| | | if (value.formStatus == "edit") { |
| | | // let params = { ...value, id:value.parentId, codeStatus: '1' }; |
| | | // delete params.parentId |
| | | updateChild({ ...value, codeStatus: '1' }).then((res) => { |
| | | if (res.code === 200) { |
| | | this.$message.success("操作成功"); |
| | | this.$refs.addSublevelForm.closeDialog(); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | if (this.$route.query.id) { |
| | | addProgenitor({ ...value, codeStatus: '1' }).then((res) => { |
| | | if (res.code === 200) { |
| | | this.$message.success("操作成功"); |
| | | this.$refs.addSublevelForm.closeDialog(); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | if (this.isAddingNode) { |
| | | // 新增节点的处理逻辑 |
| | | const nodeModel = this.selectedNode; |
| | |
| | | this.graphData.nodes.push({ |
| | | nodeId: childId, |
| | | label: nextLevel, |
| | | number: value.inoculateNo.trim(), |
| | | number: value.strainCode.trim(), |
| | | status: value.status, |
| | | data: value, |
| | | style: { |
| | |
| | | this.$refs.addSublevelPlan.openInitData({ |
| | | ...nodeModel.data, |
| | | label: nodeModel.label, |
| | | strainName: this.form.strainName, |
| | | strainCode: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | strainCode1: this.form.strainCode, |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | formStatus: "addCount", |
| | | }); |
| | | } else { |
| | | this.$refs.planForm.openInitData({ |
| | |
| | | strainCode: this.form.strainCode, |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | formStatus: "addCount", |
| | | }); |
| | | } |
| | | }, |
| | | handleAddPlan(value) { |
| | | console.log('2222222222222222222', value) |
| | | if (value.formStatus == "edit") { |
| | | let params = { ...value, id: value.parentId, codeStatus: '1' }; |
| | | delete params.parentId |
| | | updateChild({ ...params }).then((res) => { |
| | | if (res.code === 200) { |
| | | this.$message.success("操作成功"); |
| | | this.$refs.planForm.closeDialog(); |
| | | this.$refs.addSublevelPlan.closeDialog(); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | if (this.$route.query.id) { |
| | | if (value.formStatus == "addCount") { |
| | | let params = { |
| | | parentId: value.id, |
| | | generationCount: value.generationCount, |
| | | vaccinateSignature: value.vaccinateSignature, |
| | | codeStatus: '1' |
| | | }; |
| | | addCount(params).then((res) => { |
| | | if (res.code === 200) { |
| | | this.$message.success("操作成功"); |
| | | this.$refs.planForm.closeDialog(); |
| | | this.$refs.addSublevelPlan.closeDialog(); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | } else { |
| | | let params = { |
| | | id: value.id, |
| | | generationCount: value.generationCount, |
| | | vaccinateSignature: value.vaccinateSignature, |
| | | codeStatus: '1' |
| | | }; |
| | | addProgenitorChild(params).then((res) => { |
| | | if (res.code === 200) { |
| | | this.$message.success("操作成功"); |
| | | this.$refs.planForm.closeDialog(); |
| | | this.$refs.addSublevelPlan.closeDialog(); |
| | | this.reloadData(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | return; |
| | | } |
| | | const nodeModel = this.selectedNode; |
| | | const generationId = `generation-${++this.nodeCount}`; |
| | | |
| | |
| | | } |
| | | |
| | | const nodeModel = this.selectedNode; |
| | | |
| | | if (nodeModel.label === "母代") { |
| | | this.$refs.parentForm.openInitData({ |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | ...nodeModel.data, |
| | | status: "detail", |
| | | formStatus: "detail", |
| | | }); |
| | | } else if (nodeModel.label === "子代" || nodeModel.label === "孙代") { |
| | | this.dialogTitle = `${nodeModel.label}详情`; |
| | | this.$refs.addSublevelForm.openInitData({ |
| | | strainCode1: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | title: `${nodeModel.label}详情`, |
| | | form: { ...nodeModel.data }, |
| | | }); |
| | | } else if (nodeModel.label === "传代计划数") { |
| | | return; |
| | | const nodeIndex = this.graphData.nodes.findIndex( |
| | | (n) => n.nodeId === nodeModel.nodeId |
| | | ); |
| | | if (this.graphData.nodes[nodeIndex - 1].label === "子代") { |
| | | this.$refs.addSublevelPlan.openInitData({ |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainCode1: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | ...nodeModel.data, |
| | | status: "detail", |
| | | }); |
| | | } else { |
| | | this.$refs.planForm.openInitData({ |
| | | strainSourceStart: this.form.strainSourceStart, |
| | | strainSourceEnd: this.form.strainSourceEnd, |
| | | strainCode1: this.form.strainCode, |
| | | strainName1: this.form.strainName, |
| | | ...nodeModel.data, |
| | | status: "detail", |
| | | }); |
| | |
| | | padding: 0 20px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .title { |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .chart { |
| | |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | #mountNode { |
| | | .mount-node { |
| | | flex: 1; |
| | | width: 100%; |
| | | min-height: 500px; |