| | |
| | | <template> |
| | | <div> |
| | | <Card> |
| | | <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" v-if="!isReadOnly"> |
| | | <el-button @click="showChoose = true" 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 ref="form" :model="form" :rules="rules" inline label-position="top"> |
| | | <div class="header-title" style="width: 100%"> |
| | | <div class="header-title-left"> |
| | |
| | | </div> |
| | | <div class="flex" style="margin-bottom: 20px"> |
| | | <div class="tabs"> |
| | | <div :class="{ active: activeTab === 'strain' }" @click="activeTab = 'strain'"> |
| | | <div :class="{ active: activeTab === 'strain' }" @click="ChangeTab('strain')"> |
| | | 来源菌株 |
| | | </div> |
| | | <div :class="{ active: activeTab === 'material' }" @click="activeTab = 'material'"> |
| | | <div :class="{ active: activeTab === 'material' }" @click="ChangeTab('material')"> |
| | | 来源物资 |
| | | </div> |
| | | </div> |
| | |
| | | <!-- 来源菌株 --> |
| | | <el-row v-if="activeTab === 'strain'" :gutter="10"> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8"> |
| | | <el-form-item label="菌株编号" prop="strainCode" required> |
| | | <el-input v-model="form.strainCode" class="w-380" placeholder="请输入菌株编号" /> |
| | | <el-form-item label="菌株编号" prop="strainCode"> |
| | | <el-input :disabled="isReadOnly" v-model="form.strainCode" class="w-380" |
| | | placeholder="请输入菌株编号" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8"> |
| | | <el-form-item label="菌株名称" prop="strainName" required> |
| | | <el-input v-model="form.strainName" class="w-380" placeholder="请输入菌株名称" /> |
| | | <el-form-item label="菌株名称" prop="strainName"> |
| | | <el-input :disabled="isReadOnly" v-model="form.strainName" class="w-380" |
| | | placeholder="请输入菌株名称" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8"> |
| | | <el-form-item label="培养基配方" prop="mediumFormula" required> |
| | | <el-input v-model="form.mediumFormula" class="w-380" placeholder="请输入培养基配方" /> |
| | | <el-form-item label="培养基配方" prop="formula"> |
| | | <el-input :disabled="isReadOnly" v-model="form.formula" class="w-380" |
| | | placeholder="请输入培养基配方" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- 来源物资 --> |
| | | <el-row v-if="activeTab === 'material'" :gutter="10"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="来源物资、时间及批号" prop="materialCode" required> |
| | | <el-input v-model="form.materialCode" placeholder="请输入物资编号" /> |
| | | <el-form-item label="来源物资、时间及批号" prop="sourceMaterialTimeBatchNumber"> |
| | | <el-input :disabled="isReadOnly" v-model="form.sourceMaterialTimeBatchNumber" |
| | | placeholder="请输入物资编号" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="培养基配方" prop="materialName" required> |
| | | <el-input v-model="form.materialName" placeholder="请输入物资名称" /> |
| | | <el-form-item label="培养基配方" prop="formula"> |
| | | <el-input :disabled="isReadOnly" v-model="form.formula" placeholder="请输入培养基配方" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="分离菌落编号" prop="materialDescription" required> |
| | | <el-input v-model="form.materialDescription" placeholder="请输入物资描述" /> |
| | | <el-form-item label="分离菌落编号" prop="separateColonyNumber"> |
| | | <el-input :disabled="isReadOnly" v-model="form.separateColonyNumber" |
| | | placeholder="请输入分离菌落编号" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </div> |
| | | <el-row :gutter="10"> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6"> |
| | | <el-form-item label="培养基" prop="strainCode" required> |
| | | <el-input v-model="form.strainCode" class="w-380" placeholder="请输入培养基" /> |
| | | <el-form-item label="培养基" prop="cultureMedium"> |
| | | <el-input :disabled="isReadOnly" v-model="form.cultureMedium" class="w-380" |
| | | placeholder="请输入培养基" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6"> |
| | | <el-form-item label="培养温度" prop="strainName" required> |
| | | <el-input v-model="form.strainName" class="w-380" placeholder="请输入培养温度" /> |
| | | <el-form-item label="培养温度" prop="temperature"> |
| | | <el-input :disabled="isReadOnly" v-model="form.temperature" class="w-380" |
| | | placeholder="请输入培养温度" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6"> |
| | | <el-form-item label="需氧类型" prop="mediumFormula" required> |
| | | <el-input v-model="form.mediumFormula" class="w-380" placeholder="请输入需氧类型" /> |
| | | <el-form-item label="需氧类型" prop="aerobicType"> |
| | | <el-select :disabled="isReadOnly" v-model="form.aerobicType" class="w-380" |
| | | placeholder="请选择需氧类型"> |
| | | <el-option label="专性需氧" :value="1"></el-option> |
| | | <el-option label="专性厌氧" :value="2"></el-option> |
| | | <el-option label="兼性需氧" :value="3"></el-option> |
| | | <el-option label="耐氧厌氧" :value="4"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6"> |
| | | <el-form-item label="培养时间" prop="mediumFormula" required> |
| | | <el-input v-model="form.mediumFormula" class="w-380" placeholder="请输入培养时间" /> |
| | | <el-form-item label="培养时间" prop="cultureTime"> |
| | | <el-input :disabled="isReadOnly" v-model="form.cultureTime" class="w-380" |
| | | placeholder="请输入培养时间" /> |
| | | <!-- <el-date-picker v-model="form.cultureTime" class="w-380" placeholder="请选择培养时间" type="date" value-format="yyyy-MM-dd" /> --> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <div class="header-title" style="margin-top: 20px;"> |
| | | <div class="header-title-left"> |
| | | <img src="@/assets/public/headercard.png" /> |
| | | <div>一、培养基分离记录</div> |
| | | <div>一、培养皿分离记录</div> |
| | | </div> |
| | | <div class="header-title-right"> |
| | | <el-button @click="showSeparationDialog = true" class="el-icon-circle-plus-outline" type="primary"> |
| | | <el-button @click="handleAddSeparation" v-if="canEditRecord" |
| | | class="el-icon-circle-plus-outline" type="primary"> |
| | | 新增培养皿分离记录</el-button> |
| | | </div> |
| | | </div> |
| | | <Table :height="null" :queryForm="queryForm" :total="0"> |
| | | <template> |
| | | <el-table-column prop="name" label="培养皿序号" /> |
| | | <el-table-column prop="age" label="分离菌落编号" /> |
| | | <el-table-column prop="age" label="接种操作人签字" /> |
| | | <el-table-column prop="age" label="操作时间" /> |
| | | <el-table-column prop="address" label="操作"> |
| | | <template slot-scope="scope"><el-button type="text" |
| | | @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button type="text" |
| | | @click="handleEdit(scope.row)">删除</el-button></template> |
| | | </el-table-column> |
| | | </template> |
| | | <Table ref="separationTable" :data="separationTableData" :height="null" |
| | | :total="form.separationOfCultureDishesList.length" :queryForm="separationPagination" :type="2" |
| | | @handleCurrentChange="handleSeparationPageChange" @handleSizeChange="handleSeparationSizeChange"> |
| | | <el-table-column width="100" type="index" label="序号" /> |
| | | <el-table-column prop="petriDishNumber" label="培养皿编号" /> |
| | | <el-table-column prop="separateBacterialColoniesCode" label="分离菌落编号" /> |
| | | <el-table-column prop="handleSignature" label="接种操作人签字"> |
| | | <template slot-scope="scope"> |
| | | <el-image :preview-src-list="[getFullUrl(scope.row.handleSignature)]" style="width: 120px;height: 48px;" |
| | | :src="getFullUrl(scope.row.handleSignature)" alt="操作人签字" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="操作时间" /> |
| | | <el-table-column prop="address" label="操作" v-if="canEditRecord"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEditSeparation(scope.row, scope.$index)" |
| | | v-if="canEditRecord">编辑</el-button> |
| | | <el-button type="text" @click="handleDeleteSeparation(scope.$index)" |
| | | v-if="canEditRecord">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | <div class="header-title" style="margin-top: 20px;"> |
| | | <div class="header-title-left"> |
| | |
| | | <div>二、培养皿生物学形态观察记录</div> |
| | | </div> |
| | | <div class="header-title-right"> |
| | | <el-button @click="showObservationDialog = true" class="el-icon-circle-plus-outline" type="primary"> |
| | | <el-button @click="handleAddObservation" v-if="canEditRecord" |
| | | class="el-icon-circle-plus-outline" type="primary"> |
| | | 新增观察记录</el-button> |
| | | </div> |
| | | </div> |
| | | <Table :height="null" :queryForm="queryForm" :total="0"> |
| | | <template> |
| | | <el-table-column prop="age" label="分离菌落编号" /> |
| | | <el-table-column prop="age" label="形状强壮度排名" /> |
| | | <el-table-column prop="address" label="操作"> |
| | | <template slot-scope="scope"><el-button type="text" |
| | | @click="handleEdit(scope.row)">形态记录</el-button> |
| | | <el-button type="text" |
| | | @click="handleEdit(scope.row)">删除</el-button></template> |
| | | </el-table-column> |
| | | </template> |
| | | <Table :data="observationTableData" :total="form.observationOfPetriDishes.length" |
| | | :queryForm="observationPagination" :height="null" :type="2" @handleCurrentChange="handleObservationPageChange" |
| | | @handleSizeChange="handleObservationSizeChange"> |
| | | <el-table-column prop="separateColonyCode" label="分离菌落编号" /> |
| | | <el-table-column prop="strength" label="形状强壮度排名" /> |
| | | <el-table-column prop="address" label="操作"> |
| | | <template slot-scope="scope"> |
| | | <!-- <el-button type="text" @click="handleEditObservation(scope.row)" v-if="!$route.query.isDetail">编辑</el-button> --> |
| | | <el-button type="text" @click="handleEditObservation(scope.row)">形态记录</el-button> |
| | | <el-button type="text" @click="handleDeleteObservation(scope.$index)" |
| | | v-if="canEditRecord">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | <div class="header-title" style="margin-top: 20px;"> |
| | | <div class="header-title-left"> |
| | |
| | | <div>三、接种斜面记录</div> |
| | | </div> |
| | | <div class="header-title-right"> |
| | | <el-button @click="showInoculationDialog = true" class="el-icon-circle-plus-outline" type="primary"> |
| | | <el-button @click="handleAddInoculation" v-if="canEditRecord" |
| | | class="el-icon-circle-plus-outline" type="primary"> |
| | | 新增斜面记录</el-button> |
| | | </div> |
| | | </div> |
| | | <Table :height="null" :queryForm="queryForm" :total="0"> |
| | | <template> |
| | | <el-table-column prop="age" label="分离菌落编号" /> |
| | | <el-table-column prop="age" label="接种斜面编号" /> |
| | | <el-table-column prop="age" label="接种操作人" /> |
| | | <el-table-column prop="age" label="接种操作人签字" /> |
| | | <el-table-column prop="age" label="接种操作时间" /> |
| | | <el-table-column prop="age" label="入库/废弃" /> |
| | | <el-table-column prop="age" label="入库总数(只)" /> |
| | | <el-table-column prop="age" label="菌种保藏人签字" /> |
| | | <el-table-column prop="age" label="入库保藏/废弃时间" /> |
| | | |
| | | <el-table-column prop="address" label="操作"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" |
| | | @click="handleEdit(scope.row)">删除</el-button></template> |
| | | </el-table-column> |
| | | </template> |
| | | <Table :data="inoculationTableData" :total="form.vaccinationSlopes.length" :queryForm="inoculationPagination" |
| | | :height="null" :type="2" @handleCurrentChange="handleInoculationPageChange" |
| | | @handleSizeChange="handleInoculationSizeChange" border style="width: 100%; margin-bottom: 16px;" |
| | | :span-method="inoculationRowSpan"> |
| | | <el-table-column prop="separateColonyCode" label="分离菌落编号" /> |
| | | <el-table-column prop="vaccinationSlopeCode" label="接种斜面编号" /> |
| | | <el-table-column prop="handleName" label="接种操作人" /> |
| | | <el-table-column prop="handleSignature" label="接种操作人签字"> |
| | | <template slot-scope="scope"> |
| | | <el-image v-if="scope.row.handleSignature" :preview-src-list="[getFullUrl(scope.row.handleSignature)]" |
| | | style="width: 120px;height: 48px;" :src="getFullUrl(scope.row.handleSignature)" alt="操作人签字" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="handleTime" label="接种操作时间" /> |
| | | <el-table-column prop="handleType" label="入库/废弃"> |
| | | <template slot-scope="scope"> |
| | | {{ scope.row.handleType === '保存' ? '入库' : '废弃' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="入库总数(只)"> |
| | | <template slot-scope="scope"> |
| | | <span v-if="scope.$index === firstInoculationOrDiscardIndex">{{ totalInoculationCount }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="preserveSignature" label="菌种保藏人签字"> |
| | | <template slot-scope="scope"> |
| | | <el-image v-if="scope.row.preserveSignature" :preview-src-list="[getFullUrl(scope.row.preserveSignature)]" |
| | | style="width: 120px;height: 48px;" :src="getFullUrl(scope.row.preserveSignature)" alt="操作人签字" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="preserveTime" label="入库保藏/废弃时间" /> |
| | | <el-table-column label="操作" v-if="canEditRecord || canEngineerConfirm"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEditInoculation(scope.row, scope.$index)" |
| | | v-if="canEditRecord">编辑</el-button> |
| | | <el-button type="text" @click="handleConfirmStorageClick(scope.row, scope.$index)" |
| | | v-if="canEngineerConfirm && !scope.row.preserveSignature">确认入库</el-button> |
| | | <el-button type="text" @click="handleDeleteInoculation(scope.$index)" |
| | | v-if="canEditRecord && !scope.row.preserveSignature">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | <div class="header-title" style="margin-top: 20px;"> |
| | | <div class="header-title-left"> |
| | |
| | | <div>四、菌种保藏记录</div> |
| | | </div> |
| | | <div class="header-title-right"> |
| | | <el-button @click="showPreserveDialog = true" class="el-icon-circle-plus-outline" type="primary"> |
| | | <el-button @click="handleAddPreserve" v-if="canEditRecord" |
| | | class="el-icon-circle-plus-outline" type="primary"> |
| | | 新增菌种保藏记录</el-button> |
| | | </div> |
| | | </div> |
| | | <Table :height="null" :queryForm="queryForm" :total="0"> |
| | | <template> |
| | | <el-table-column prop="age" label="用于保藏的菌种编号" /> |
| | | <el-table-column prop="age" label="实验验证结论" /> |
| | | <el-table-column prop="age" label="保藏方法" /> |
| | | <el-table-column prop="age" label="保藏菌种编号" /> |
| | | <el-table-column prop="age" label="菌种保藏人签字" /> |
| | | <el-table-column prop="age" label="保藏时间" /> |
| | | <el-table-column prop="address" label="操作"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" |
| | | @click="handleEdit(scope.row)">删除</el-button></template> |
| | | </el-table-column> |
| | | </template> |
| | | <Table :data="preserveTableData" :total="form.culturePreservations.length" :queryForm="preservePagination" |
| | | :height="null" :type="2" @handleCurrentChange="handlePreservePageChange" |
| | | @handleSizeChange="handlePreserveSizeChange"> |
| | | <el-table-column prop="forPreserveCode" label="用于保藏的菌种编号" /> |
| | | <el-table-column prop="verificationConclusion" label="实验验证结论" /> |
| | | <el-table-column prop="preserveMethod" label="保藏方法" /> |
| | | <el-table-column prop="preserveCode" label="保藏菌种编号" /> |
| | | <el-table-column prop="handleSignature" label="菌种操作人签字"> |
| | | <template slot-scope="scope"> |
| | | <el-image v-if="scope.row.handleSignature" :preview-src-list="[getFullUrl(scope.row.handleSignature)]" |
| | | style="width: 120px;height: 48px;" :src="getFullUrl(scope.row.handleSignature)" alt="签字" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="handleTime" label="操作人" /> |
| | | <el-table-column prop="preserveSignature" label="菌种保藏人签字"> |
| | | <template slot-scope="scope"> |
| | | <el-image v-if="scope.row.preserveSignature" :preview-src-list="[getFullUrl(scope.row.preserveSignature)]" |
| | | style="width: 120px;height: 48px;" :src="getFullUrl(scope.row.preserveSignature)" alt="签字" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="preserveTime" label="保藏时间" /> |
| | | <el-table-column label="操作" v-if="canEditRecord || canEngineerConfirm"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleEditPreserve(scope.row, scope.$index)" |
| | | v-if="canEditRecord">编辑</el-button> |
| | | <el-button type="text" @click="handleConfirmPreserve(scope.row, scope.$index)" |
| | | v-if="canEngineerConfirm && !scope.row.preserveSignature">确认入库</el-button> |
| | | <el-button type="text" @click="handleDeletePreserve(scope.$index)" |
| | | v-if="canEditRecord && !scope.row.preserveSignature">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </Table> |
| | | <!-- 弹窗组件 --> |
| | | <SeparationRecordDialog |
| | | :visible.sync="showSeparationDialog" |
| | | @confirm="handleSeparationConfirm" |
| | | /> |
| | | <SlantRecordDialog |
| | | :visible.sync="showObservationDialog" |
| | | @ok="handleObservationConfirm" |
| | | /> |
| | | <InoculationSlopeRecordDialog |
| | | :visible.sync="showInoculationDialog" |
| | | @save="handleInoculationConfirm" |
| | | /> |
| | | <PreserveStrainRecordDialog |
| | | :visible.sync="showPreserveDialog" |
| | | @save="handlePreserveConfirm" |
| | | /> |
| | | <div class="end-btn"> |
| | | <el-button type="primary">发送</el-button> |
| | | <el-button type="default">存草稿</el-button> |
| | | <SeparationRecordDialog :visible.sync="showSeparationDialog" :editData="editSeparationData" |
| | | @confirm="handleSeparationConfirm" @close="resetSeparationEdit" /> |
| | | <SlantRecordDialog :visible.sync="showObservationDialog" :editData="editObservationData" :read-only="isReadOnly" |
| | | @ok="handleObservationConfirm" /> |
| | | <InoculationSlopeRecordDialog :visible.sync="showInoculationDialog" :editData="editInoculationData" |
| | | @save="handleInoculationConfirm" /> |
| | | <PreserveStrainRecordDialog :visible.sync="showPreserveDialog" :editData="editPreserveData" |
| | | @save="handlePreserveConfirm" /> |
| | | <ConfirmStorageDialog :visible.sync="showConfirmStorageDialog" :editData="editInoculationData" |
| | | @confirm="handleConfirmStorage" /> |
| | | <ConfirmPreserveDialog :visible.sync="showConfirmPreserveDialog" :editData="editPreserveData" |
| | | @confirm="handleConfirmPreserveSubmit" /> |
| | | <div class="end-btn" style="margin-top: 20px;" v-if="canEditRecord"> |
| | | <el-button type="primary" v-if="[1, 4].includes(roleType)" @click="handleSubmit(1)">提交</el-button> |
| | | <el-button v-if="[1, 4].includes(roleType)" type="primary" @click="handleSubmit(3)">同步给保藏人</el-button> |
| | | <el-button v-if="!$route.query.isDetail && roleType != 1" type="default" @click="handleSubmit(2)">存草稿</el-button> |
| | | </div> |
| | | </el-form> |
| | | </Card> |
| | | |
| | | <chooseProject v-if="!isReadOnly" @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject> |
| | | </div> |
| | | </template> |
| | | <script> |
| | |
| | | import SlantRecordDialog from "./SlantRecordDialog.vue"; |
| | | import InoculationSlopeRecordDialog from "./inoculation-slope-record-dialog.vue"; |
| | | import PreserveStrainRecordDialog from "./preserve-strain-record-dialog.vue"; |
| | | |
| | | import ConfirmStorageDialog from "./confirm-storage-dialog.vue"; |
| | | import ConfirmPreserveDialog from "./confirm-preserve-dialog.vue"; |
| | | import { getFullUrl } from "@/utils/utils"; |
| | | import { add, detail, edit, vaccinationSlopesConfirm, culturePreservationsConfirm } from './service' |
| | | import ChooseProject from "@/components/chooseProject/index.vue"; |
| | | export default { |
| | | components: { |
| | | ChooseProject, |
| | | AiEditor, |
| | | SeparationRecordDialog, |
| | | SlantRecordDialog, |
| | | InoculationSlopeRecordDialog, |
| | | PreserveStrainRecordDialog, |
| | | ConfirmStorageDialog, |
| | | ConfirmPreserveDialog, |
| | | |
| | | }, |
| | | name: "AddBreedingRecord", |
| | | name: "BreedingRecordAdd", |
| | | data() { |
| | | return { |
| | | cacheForm: null, |
| | | form: { |
| | | strainCode: "", |
| | | strainName: "", |
| | | mediumFormula: "", |
| | | materialCode: "", |
| | | materialName: "", |
| | | materialDescription: "", |
| | | planName: "", |
| | | planCode: "", |
| | | stage: "", |
| | | creator: "", |
| | | createTime: "", |
| | | approvalComment: "", |
| | | status: "pending", |
| | | approver: "", |
| | | approveTime: "", |
| | | id: '', // 主键 |
| | | strainCode: '', // 菌株编号 |
| | | strainName: '', // 菌株名称 |
| | | formula: '', // 培养基配方 |
| | | cultureMedium: '', // 培养基 |
| | | cultureTime: '', // 培养时间 |
| | | aerobicType: '', // 需氧类型 |
| | | temperature: '', // 培养温度 |
| | | status: '', // 状态 |
| | | createBy: '', // 创建人 |
| | | createTime: '', // 创建时间 |
| | | updateBy: '', // 修改人 |
| | | updateTime: '', // 修改时间 |
| | | disabled: 0, // 是否删除 |
| | | preserveSource: '', // 来源类型 |
| | | separateColonyNumber: '', // 分离菌落编号 |
| | | sourceMaterialTimeBatchNumber: '', // 来源物资存值批号 |
| | | // 下面是 array 类型字段 |
| | | observationOfPetriDishes: [], |
| | | separationOfCultureDishesList: [], |
| | | vaccinationSlopes: [], |
| | | // 兼容原有表单字段 |
| | | mediumFormula: '', |
| | | materialCode: '', |
| | | materialName: '', |
| | | materialDescription: '', |
| | | projectId: '', |
| | | planName: '', |
| | | planCode: '', |
| | | stage: '', |
| | | creator: '', |
| | | approvalComment: '', |
| | | approver: '', |
| | | approveTime: '', |
| | | culturePreservations: [], // 新增:菌种保藏记录数组 |
| | | }, |
| | | rules: { |
| | | strainCode: [{ required: true, message: "请输入菌株编号", trigger: "blur" }], |
| | | strainName: [{ required: true, message: "请输入菌株名称", trigger: "blur" }], |
| | | mediumFormula: [{ required: true, message: "请输入培养基配方", trigger: "blur" }], |
| | | materialCode: [{ required: true, message: "请输入物资编号", trigger: "blur" }], |
| | | formula: [{ required: true, message: "请输入培养基配方", trigger: "blur" }], |
| | | cultureMedium: [{ required: true, message: "请输入培养基", trigger: "blur" }], |
| | | cultureTime: [{ required: true, message: "请输入培养时间", trigger: "blur" }], |
| | | aerobicType: [{ required: true, message: "请输入需氧类型", trigger: "blur" }], |
| | | temperature: [{ required: true, message: "请输入培养温度", trigger: "blur" }], |
| | | sourceMaterialTimeBatchNumber: [{ required: true, message: "请输入物资编号", trigger: "blur" }], |
| | | materialName: [{ required: true, message: "请输入物资名称", trigger: "blur" }], |
| | | materialDescription: [{ required: true, message: "请输入物资描述", trigger: "blur" }], |
| | | }, |
| | |
| | | radio1: 1, |
| | | status: "1", |
| | | remark: "", |
| | | projectData: [], // 存储选中的项目组数据 |
| | | queryForm: {}, |
| | | showSeparationDialog: false, |
| | | showObservationDialog: false, |
| | | showInoculationDialog: false, |
| | | showPreserveDialog: false, |
| | | showConfirmStorageDialog: false, |
| | | showConfirmPreserveDialog: false, |
| | | editSeparationIndex: null, |
| | | editSeparationData: null, |
| | | editObservationData: null, |
| | | editInoculationIndex: null, |
| | | editInoculationData: null, |
| | | editPreserveIndex: null, |
| | | editPreserveData: null, |
| | | roleType: Number(JSON.parse(sessionStorage.getItem('userInfo')).roleType || 1), // 1.超级管理员 2.审批人 3.工程师 4.实验员 |
| | | separationPagination: { pageNum: 1, pageSize: 5 }, |
| | | observationPagination: { pageNum: 1, pageSize: 5 }, |
| | | inoculationPagination: { pageNum: 1, pageSize: 5 }, |
| | | preservePagination: { pageNum: 1, pageSize: 5 }, |
| | | }; |
| | | }, |
| | | computed: { |
| | | isReadOnly() { |
| | | return Boolean(this.$route.query.isDetail) || Number(this.form.status) === 1 |
| | | }, |
| | | canEditRecord() { |
| | | return !this.isReadOnly && [1, 4].includes(this.roleType) |
| | | }, |
| | | canEngineerConfirm() { |
| | | return Boolean(this.$route.query.isDetail) |
| | | && this.roleType === 3 |
| | | && Number(this.form.status) === 2 |
| | | }, |
| | | totalInoculationCount() { |
| | | // 只统计入库(保存) |
| | | return this.form.vaccinationSlopes |
| | | .filter(item => item.handleType === '保存') |
| | | .length; |
| | | }, |
| | | firstInoculationOrDiscardIndex() { |
| | | // 第一个入库或废弃行 |
| | | return this.form.vaccinationSlopes.findIndex(item => item.handleType === '保存' || item.handleType === '废弃'); |
| | | }, |
| | | separationTableData() { |
| | | const { pageNum, pageSize } = this.separationPagination; |
| | | const start = (pageNum - 1) * pageSize; |
| | | return this.form.separationOfCultureDishesList.slice(start, start + pageSize); |
| | | }, |
| | | observationTableData() { |
| | | const { pageNum, pageSize } = this.observationPagination; |
| | | const start = (pageNum - 1) * pageSize; |
| | | return this.form.observationOfPetriDishes.slice(start, start + pageSize); |
| | | }, |
| | | inoculationTableData() { |
| | | const { pageNum, pageSize } = this.inoculationPagination; |
| | | const start = (pageNum - 1) * pageSize; |
| | | return this.form.vaccinationSlopes.slice(start, start + pageSize); |
| | | }, |
| | | preserveTableData() { |
| | | const { pageNum, pageSize } = this.preservePagination; |
| | | const start = (pageNum - 1) * pageSize; |
| | | return this.form.culturePreservations.slice(start, start + pageSize); |
| | | } |
| | | }, |
| | | activated() { |
| | | if (this.cacheForm) { |
| | | this.form = this.cacheForm; |
| | | } |
| | | if (this.$route.query.id && !this.cacheForm) { |
| | | this.getDetail() |
| | | } |
| | | }, |
| | | deactivated() { |
| | | this.cacheForm = JSON.parse(JSON.stringify(this.form)); |
| | | }, |
| | | methods: { |
| | | getProjectData(data) { |
| | | this.projectData = [data]; // 将选中的项目组数据存储到数组中 |
| | | this.showChoose = false; |
| | | this.form.projectId = this.projectData[0].id; |
| | | }, |
| | | getFullUrl(url) { |
| | | if (url) { |
| | | return getFullUrl(url) |
| | | } |
| | | }, |
| | | ChangeTab(tab) { |
| | | if (this.isReadOnly) return |
| | | this.activeTab = tab |
| | | this.form.preserveSource = tab === 'strain' ? 1 : 2 |
| | | }, |
| | | async getDetail() { |
| | | const response = await detail({ id: this.$route.query.id }) |
| | | const res = response.data || response |
| | | if (res.preserveSource == 1) { |
| | | this.activeTab = 'strain' |
| | | } else { |
| | | this.activeTab = 'material' |
| | | } |
| | | res.vaccinationSlopes = (res.vaccinationSlopes || []).map(item => { |
| | | return { |
| | | ...item, |
| | | handleType: item.handleType === 1 ? '保存' : '废弃' |
| | | } |
| | | }) |
| | | this.form = { |
| | | ...this.form, |
| | | ...res, |
| | | observationOfPetriDishes: res.observationOfPetriDishes || [], |
| | | separationOfCultureDishesList: res.separationOfCultureDishesList || [], |
| | | culturePreservations: res.culturePreservations || [] |
| | | } |
| | | this.projectData = res.tprojectTeamList || []; |
| | | }, |
| | | handleSeparationConfirm(data) { |
| | | console.log("培养皿分离记录确认", data); |
| | | if (this.editSeparationIndex !== null) { |
| | | // 编辑 |
| | | this.$set(this.form.separationOfCultureDishesList, this.editSeparationIndex, data); |
| | | this.resetSeparationEdit(); |
| | | } else { |
| | | // 新增 |
| | | console.log('新增', data) |
| | | this.form.separationOfCultureDishesList.push(data); |
| | | } |
| | | }, |
| | | handleObservationConfirm(data) { |
| | | console.log("培养皿观察记录确认", data); |
| | | if (this.editObservationData) { |
| | | // 编辑 |
| | | const index = this.form.observationOfPetriDishes.findIndex(item => item.id === data.id); |
| | | if (index !== -1) { |
| | | this.$set(this.form.observationOfPetriDishes, index, data); |
| | | } |
| | | } else { |
| | | // 新增 |
| | | this.form.observationOfPetriDishes.push({ |
| | | ...data, |
| | | id: Date.now().toString(), // 临时ID,实际应该由后端生成 |
| | | }); |
| | | } |
| | | this.editObservationData = null; |
| | | }, |
| | | handleInoculationConfirm(data) { |
| | | console.log("接种斜面记录确认", data); |
| | | console.log('接种', data) |
| | | if (this.editInoculationIndex !== null) { |
| | | // 编辑模式:更新指定索引的数据 |
| | | this.$set(this.form.vaccinationSlopes, this.editInoculationIndex, { |
| | | ...data, |
| | | // 保留原有的ID和其他必要字段 |
| | | id: this.form.vaccinationSlopes[this.editInoculationIndex].id |
| | | }); |
| | | } else { |
| | | // 新增模式:添加新数据 |
| | | this.form.vaccinationSlopes.push({ |
| | | ...data, |
| | | id: Date.now().toString() // 临时ID,实际应该由后端生成 |
| | | }); |
| | | } |
| | | this.showInoculationDialog = false; |
| | | this.editInoculationIndex = null; |
| | | this.editInoculationData = null; |
| | | }, |
| | | handlePreserveConfirm(data) { |
| | | console.log("菌种保藏记录确认", data); |
| | | if (this.editPreserveIndex !== null) { |
| | | // 编辑 |
| | | this.$set(this.form.culturePreservations, this.editPreserveIndex, data); |
| | | } else { |
| | | // 新增 |
| | | this.form.culturePreservations.push(data); |
| | | } |
| | | this.showPreserveDialog = false; |
| | | this.editPreserveIndex = null; |
| | | this.editPreserveData = null; |
| | | }, |
| | | handleSubmit(type) { |
| | | if (this.isReadOnly) return |
| | | if (type === 1) { |
| | | if (!this.form.id || Number(this.form.status) !== 2) { |
| | | this.$message.warning('请先同步给保藏人并完成入库确认') |
| | | return |
| | | } |
| | | const hasUnconfirmedSlope = this.form.vaccinationSlopes.some(item => !item.preserveId && !item.preserveSignature) |
| | | const hasUnconfirmedPreservation = this.form.culturePreservations.some(item => !item.preserveId && !item.preserveSignature) |
| | | if (hasUnconfirmedSlope || hasUnconfirmedPreservation) { |
| | | this.$message.warning('存在未确认的接种斜面或菌种保藏记录,不能提交') |
| | | return |
| | | } |
| | | } |
| | | this.$refs.form.validate(async (valid) => { |
| | | if (!valid) return; |
| | | try { |
| | | const status = type === 1 ? 1 : type === 3 ? 2 : 3 |
| | | const payload = { |
| | | ...this.form, |
| | | preserveSource: this.activeTab === 'material' ? 2 : 1, |
| | | status, |
| | | isDraft: status === 2 ? this.form.isDraft : 0, |
| | | vaccinationSlopes: (this.form.vaccinationSlopes || []).map(item => ({ |
| | | ...item, |
| | | handleType: item.handleType === '保存' || item.handleType === 1 ? 1 : 2 |
| | | })) |
| | | } |
| | | const request = payload.id ? edit(payload) : add(payload) |
| | | const res = await request |
| | | if (res.code === 200) { |
| | | this.$message.success(payload.id ? '编辑成功' : '添加成功') |
| | | this.cacheForm = null |
| | | this.$closeCurrentView('/strain/breeding-record') |
| | | } else { |
| | | this.$message.error(res.msg || (payload.id ? '编辑失败' : '添加失败')) |
| | | } |
| | | |
| | | } catch (e) { |
| | | this.$message.error(this.form.id ? '编辑失败' : '添加失败'); |
| | | } |
| | | }); |
| | | }, |
| | | handleEditSeparation(row, index) { |
| | | this.editSeparationIndex = index; |
| | | this.editSeparationData = { ...row }; |
| | | this.showSeparationDialog = true; |
| | | }, |
| | | handleDeleteSeparation(index) { |
| | | this.form.separationOfCultureDishesList.splice(index, 1); |
| | | // 如果当前页数据被删空,自动回到上一页 |
| | | const total = this.form.separationOfCultureDishesList.length; |
| | | const { pageNum, pageSize } = this.separationPagination; |
| | | if (total && (pageNum - 1) * pageSize >= total) { |
| | | this.separationPagination.pageNum = Math.max(1, pageNum - 1); |
| | | } |
| | | }, |
| | | resetSeparationEdit() { |
| | | this.editSeparationIndex = null; |
| | | this.editSeparationData = null; |
| | | }, |
| | | handleAddSeparation() { |
| | | this.editSeparationIndex = null; |
| | | this.editSeparationData = null; |
| | | this.showSeparationDialog = true; |
| | | }, |
| | | handleAddObservation() { |
| | | this.editObservationData = null; |
| | | this.showObservationDialog = true; |
| | | }, |
| | | handleEditObservation(row) { |
| | | this.editObservationData = { ...row }; |
| | | this.showObservationDialog = true; |
| | | }, |
| | | handleDeleteObservation(index) { |
| | | this.form.observationOfPetriDishes.splice(index, 1); |
| | | const total = this.form.observationOfPetriDishes.length; |
| | | const { pageNum, pageSize } = this.observationPagination; |
| | | if (total && (pageNum - 1) * pageSize >= total) { |
| | | this.observationPagination.pageNum = Math.max(1, pageNum - 1); |
| | | } |
| | | }, |
| | | handleAddInoculation() { |
| | | this.editInoculationIndex = null; |
| | | this.editInoculationData = null; |
| | | this.showInoculationDialog = true; |
| | | }, |
| | | handleEditInoculation(row, index) { |
| | | this.editInoculationIndex = index; |
| | | // 深拷贝当前行数据,避免直接修改原数据 |
| | | this.editInoculationData = JSON.parse(JSON.stringify(row)); |
| | | this.showInoculationDialog = true; |
| | | }, |
| | | handleConfirmStorageClick(row, index) { |
| | | this.editInoculationIndex = index; |
| | | // 深拷贝当前行数据,避免直接修改原数据 |
| | | this.editInoculationData = JSON.parse(JSON.stringify(row)); |
| | | this.showConfirmStorageDialog = true; |
| | | }, |
| | | handleConfirmStorage(data) { |
| | | if (data.preserveSignature) { |
| | | vaccinationSlopesConfirm({ id: this.form.vaccinationSlopes[this.editInoculationIndex].id, preserveSignature: data.preserveSignature }).then(res => { |
| | | if (this.editInoculationIndex !== null) { |
| | | this.$set(this.form.vaccinationSlopes, this.editInoculationIndex, { |
| | | ...this.form.vaccinationSlopes[this.editInoculationIndex], |
| | | preserveSignature: data.preserveSignature, // 更新签名数据 |
| | | status: '保存' // 更新状态为保存 |
| | | }); |
| | | } |
| | | this.showConfirmStorageDialog = false; |
| | | this.editInoculationIndex = null; |
| | | this.editInoculationData = null; |
| | | }) |
| | | } |
| | | }, |
| | | handleDeleteInoculation(index) { |
| | | this.form.vaccinationSlopes.splice(index, 1); |
| | | const total = this.form.vaccinationSlopes.length; |
| | | const { pageNum, pageSize } = this.inoculationPagination; |
| | | if (total && (pageNum - 1) * pageSize >= total) { |
| | | this.inoculationPagination.pageNum = Math.max(1, pageNum - 1); |
| | | } |
| | | }, |
| | | inoculationRowSpan({ row, rowIndex, columnIndex }) { |
| | | // 入库总数(只)列合并 |
| | | if (columnIndex === 6) { |
| | | // 合并所有入库或废弃行 |
| | | const mergeCount = this.form.vaccinationSlopes.filter(item => item.handleType === '保存' || item.handleType === '废弃').length; |
| | | if (rowIndex === this.firstInoculationOrDiscardIndex) { |
| | | return { rowspan: mergeCount, colspan: 1 }; |
| | | } else if (row.handleType === '保存' || row.handleType === '废弃') { |
| | | return { rowspan: 0, colspan: 0 }; |
| | | } |
| | | } |
| | | }, |
| | | handleAddPreserve() { |
| | | this.editPreserveIndex = null; |
| | | this.editPreserveData = null; |
| | | this.showPreserveDialog = true; |
| | | }, |
| | | handleEditPreserve(row, index) { |
| | | this.editPreserveIndex = index; |
| | | this.editPreserveData = { ...row }; |
| | | this.showPreserveDialog = true; |
| | | }, |
| | | handleDeletePreserve(index) { |
| | | this.form.culturePreservations.splice(index, 1); |
| | | const total = this.form.culturePreservations.length; |
| | | const { pageNum, pageSize } = this.preservePagination; |
| | | if (total && (pageNum - 1) * pageSize >= total) { |
| | | this.preservePagination.pageNum = Math.max(1, pageNum - 1); |
| | | } |
| | | }, |
| | | handleConfirmPreserve(row, index) { |
| | | this.editPreserveIndex = index; |
| | | // 深拷贝当前行数据,避免直接修改原数据 |
| | | this.editPreserveData = JSON.parse(JSON.stringify(row)); |
| | | this.showConfirmPreserveDialog = true; |
| | | }, |
| | | handleConfirmPreserveSubmit(data) { |
| | | if (data.preserveSignature) { |
| | | culturePreservationsConfirm({ id: this.form.culturePreservations[this.editPreserveIndex].id, preserveSignature: data.preserveSignature }).then(res => { |
| | | if (this.editPreserveIndex !== null) { |
| | | this.$set(this.form.culturePreservations, this.editPreserveIndex, { |
| | | ...this.form.culturePreservations[this.editPreserveIndex], |
| | | preserveSignature: data.preserveSignature, // 更新签名数据 |
| | | preserveTime: data.preserveTime, |
| | | }); |
| | | } |
| | | this.showConfirmPreserveDialog = false; |
| | | this.editPreserveIndex = null; |
| | | this.editPreserveData = null; |
| | | }) |
| | | } |
| | | |
| | | }, |
| | | handleSeparationPageChange(val) { |
| | | this.separationPagination.pageNum = val; |
| | | }, |
| | | handleSeparationSizeChange(val) { |
| | | this.separationPagination.pageSize = val; |
| | | this.separationPagination.pageNum = 1; |
| | | }, |
| | | handleObservationPageChange(val) { |
| | | this.observationPagination.pageNum = val; |
| | | }, |
| | | handleObservationSizeChange(val) { |
| | | this.observationPagination.pageSize = val; |
| | | this.observationPagination.pageNum = 1; |
| | | }, |
| | | handleInoculationPageChange(val) { |
| | | this.inoculationPagination.pageNum = val; |
| | | }, |
| | | handleInoculationSizeChange(val) { |
| | | this.inoculationPagination.pageSize = val; |
| | | this.inoculationPagination.pageNum = 1; |
| | | }, |
| | | handlePreservePageChange(val) { |
| | | this.preservePagination.pageNum = val; |
| | | }, |
| | | handlePreserveSizeChange(val) { |
| | | this.preservePagination.pageSize = val; |
| | | this.preservePagination.pageNum = 1; |
| | | }, |
| | | }, |
| | | }; |
| | |
| | | padding: 4px; |
| | | |
| | | div { |
| | | width: 183px; |
| | | width: 178px; |
| | | height: 32px; |
| | | border-radius: 10px; |
| | | text-align: center; |