| | |
| | | <template> |
| | | <Card> |
| | | <el-form |
| | | :model="form" |
| | | :rules="rules" |
| | | ref="strainForm" |
| | | label-position="top" |
| | | class="strain-form" |
| | | > |
| | | <div class="form-grid"> |
| | | <el-form-item label="菌种编号" prop="strainNo" required> |
| | | <el-input v-model="form.strainNo" placeholder="请输入"></el-input> |
| | | <el-form :model="form" :rules="rules" ref="strainForm" label-position="top" class="strain-form"> |
| | | <div class="form-row three-columns"> |
| | | <el-form-item label="菌种编号" prop="strainCode"> |
| | | <el-input v-model="form.strainCode" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="菌种名称" prop="strainName" required> |
| | | <el-form-item label="菌种名称" prop="strainName"> |
| | | <el-input v-model="form.strainName" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="菌种来源" prop="source" required> |
| | | <el-input v-model="form.source" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="鉴定方法" prop="identificationMethod" required> |
| | | <el-input v-model="form.identificationMethod" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="特征描述" prop="characteristics" required> |
| | | <el-input v-model="form.characteristics" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="菌种保存方法" prop="preservationMethod" required> |
| | | <el-input v-model="form.preservationMethod" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="保存位置" prop="storageLocation" required> |
| | | <el-input v-model="form.storageLocation" placeholder="请输入"></el-input> |
| | | <el-form-item label="菌种来源" prop="strainSource"> |
| | | <el-input v-model="form.strainSource" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <div class="form-row"> |
| | | <el-form-item label="鉴定方法" prop="appraisalMethod"> |
| | | <el-input v-model="form.appraisalMethod" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <div class="form-row"> |
| | | <el-form-item label="特征描述" prop="features" class="full-width"> |
| | | <el-input type="textarea" v-model="form.features" :rows="4" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <div class="form-row three-columns"> |
| | | <el-form-item label="保藏位置" prop="saveLocation"> |
| | | <el-input v-model="form.saveLocation" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="菌种保存方法" prop="saveMethod"> |
| | | <el-input v-model="form.saveMethod" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | <div class="form-item-placeholder"></div> |
| | | </div> |
| | | |
| | | <div class="form-row"> |
| | | <el-form-item label="备注" prop="remarks" class="full-width"> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="form.remarks" |
| | | :rows="4" |
| | | placeholder="请输入" |
| | | ></el-input> |
| | | <el-input type="textarea" v-model="form.remark" :rows="4" placeholder="请输入"></el-input> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <div class="end-btn" style="margin-top: 38px"> |
| | | <el-button type="primary" @click="handleSubmit">提交</el-button> |
| | | <el-button @click="handleDraft">存草稿</el-button> |
| | | <el-button type="primary" @click="handleSubmit(0)">提交</el-button> |
| | | <el-button v-if="!$route.query.id" type="primary" @click="handleBatchAdd">批量新增</el-button> |
| | | <el-button @click="handleSubmit(1)">存草稿</el-button> |
| | | </div> |
| | | </el-form> |
| | | |
| | | <!-- 批量新增弹窗 --> |
| | | <el-dialog title="批量新增" :visible.sync="batchAddDialogVisible" width="520px" :close-on-click-modal="false" |
| | | :close-on-press-escape="false" custom-class="batch-add-dialog"> |
| | | <div class="dialog-content"> |
| | | <el-form :model="batchForm" ref="batchFormRef" label-position="top" class="batch-form"> |
| | | <el-form-item label="批量新增数量" prop="count" |
| | | :rules="[{ required: true, message: '请输入批量新增数量', trigger: 'blur' }]"> |
| | | <el-input v-model.number="batchForm.count" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="dialog-notice"> |
| | | <p>注意:操作批量新增后,系统会自动生成对应数量的菌种数据,</p> |
| | | <p>这些菌种的基础信息内容都是一致的,唯独菌种编号内容系统</p> |
| | | <p>不会自动生成,需要操作员自行编辑</p> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="end-btn"> |
| | | <el-button type="primary" @click="handleConfirmBatchAdd">确认新增</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 签字确认组件 --> |
| | | <SignatureCanvas |
| | | :visible.sync="signatureVisible" |
| | | @confirm="handleSignatureConfirm" |
| | | /> |
| | | <SignatureCanvas :visible.sync="signatureVisible" @confirm="handleSignatureConfirm" /> |
| | | </Card> |
| | | </template> |
| | | |
| | | <script> |
| | | import SignatureCanvas from '@/components/SignatureCanvas.vue' |
| | | import { add, edit, getDetail, addBatch } from './service' |
| | | |
| | | export default { |
| | | name: 'AddProductionCell', |
| | | name: 'StrainLibraryManageAdd', |
| | | components: { |
| | | SignatureCanvas |
| | | }, |
| | | data() { |
| | | return { |
| | | batchAddDialogVisible: false, |
| | | signatureVisible: false, |
| | | currentAction: '', // 'submit' or 'batchAdd' |
| | | batchForm: { |
| | | count: '' |
| | | }, |
| | | form: { |
| | | strainNo: '', |
| | | strainCode: '', |
| | | strainName: '', |
| | | source: '', |
| | | identificationMethod: '', |
| | | appraisalMethod: '', |
| | | characteristics: '', |
| | | storageLocation: '', |
| | | preservationMethod: '', |
| | | remarks: '' |
| | | remark: '' |
| | | }, |
| | | rules: { |
| | | strainNo: [{ required: true, message: '请输入菌种编号', trigger: 'blur' }], |
| | | strainCode: [{ |
| | | validator: (rule, value, callback) => { |
| | | if (this.currentAction === 'submit' && !value) { |
| | | callback(new Error('请输入菌种编号')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'change' |
| | | }], |
| | | strainName: [{ required: true, message: '请输入菌种名称', trigger: 'blur' }], |
| | | source: [{ required: true, message: '请输入菌种来源', trigger: 'blur' }], |
| | | identificationMethod: [{ required: true, message: '请输入鉴定方法', trigger: 'blur' }], |
| | | characteristics: [{ required: true, message: '请输入特征描述', trigger: 'blur' }], |
| | | storageLocation: [{ required: true, message: '请输入保存位置', trigger: 'blur' }], |
| | | preservationMethod: [{ required: true, message: '请输入菌种保存方法', trigger: 'blur' }] |
| | | strainSource: [{ required: true, message: '请输入菌种来源', trigger: 'blur' }], |
| | | appraisalMethod: [{ required: true, message: '请输入鉴定方法', trigger: 'blur' }], |
| | | features: [{ required: true, message: '请输入特征描述', trigger: 'blur' }], |
| | | saveLocation: [{ required: true, message: '请输入保存位置', trigger: 'blur' }], |
| | | saveMethod: [{ required: true, message: '请输入菌种保存方法', trigger: 'blur' }] |
| | | } |
| | | } |
| | | }, |
| | | activated() { |
| | | if (this.$route.query.id) { |
| | | getDetail({ id: this.$route.query.id }).then(res => { |
| | | this.form = res |
| | | }) |
| | | } |
| | | }, |
| | | watch: { |
| | | '$route.query.id'() { |
| | | this.form = { |
| | | strainCode: '', |
| | | strainName: '', |
| | | source: '', |
| | | appraisalMethod: '', |
| | | characteristics: '', |
| | | storageLocation: '', |
| | | preservationMethod: '', |
| | | remark: '' |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | handleSubmit() { |
| | | handleSubmit(isDraft) { |
| | | this.currentAction = 'submit' |
| | | this.$refs.strainForm.validate((valid) => { |
| | | if (valid) { |
| | | this.form.isDraft = isDraft |
| | | if (isDraft == 1) { |
| | | //存草稿 |
| | | this.handleSignatureConfirm('') |
| | | } else { |
| | | this.signatureVisible = true |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | handleBatchAdd() { |
| | | this.currentAction = 'batchAdd' |
| | | this.$refs.strainForm.validate((valid) => { |
| | | if (valid) { |
| | | this.batchAddDialogVisible = true |
| | | } |
| | | }) |
| | | }, |
| | | handleConfirmBatchAdd() { |
| | | this.$refs.batchFormRef.validate((valid) => { |
| | | if (valid) { |
| | | this.batchAddDialogVisible = false |
| | | this.signatureVisible = true |
| | | } |
| | | }) |
| | | }, |
| | | handleDraft() { |
| | | // 实现存草稿逻辑 |
| | | console.log('save draft', this.form) |
| | | this.$message.success('草稿保存成功') |
| | | }, |
| | | handleSignatureConfirm(signatureImage) { |
| | | this.signatureVisible = false |
| | | // 处理提交逻辑 |
| | | console.log('submit form with signature:', this.form, signatureImage) |
| | | this.$message.success('提交成功') |
| | | this.$router.back() |
| | | async handleSignatureConfirm(signatureImage) { |
| | | let requestData = { |
| | | strainCode: this.form.strainCode, |
| | | strainName: this.form.strainName, |
| | | strainSource: this.form.strainSource, |
| | | appraisalMethod: this.form.appraisalMethod, |
| | | features: this.form.features, |
| | | saveLocation: this.form.saveLocation, |
| | | saveMethod: this.form.saveMethod, |
| | | remark: this.form.remark, |
| | | signature: signatureImage, |
| | | type: 3, |
| | | }; |
| | | if (this.currentAction === 'batchAdd') { |
| | | requestData.batchCount = this.batchForm.count; |
| | | } else { |
| | | requestData.isDraft = this.form.isDraft |
| | | } |
| | | try { |
| | | if (this.$route.query.id) { |
| | | requestData.id = this.$route.query.id; |
| | | await edit(requestData); |
| | | } else if (this.currentAction === 'batchAdd') { |
| | | await addBatch(requestData); |
| | | } else { |
| | | await add(requestData); |
| | | } |
| | | this.signatureVisible = false; |
| | | this.$router.back(); |
| | | this.$message.success('操作成功'); |
| | | } catch (error) { |
| | | this.$message.error('操作失败'); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .strain-form { |
| | | padding: 0 40px; |
| | | .add-strain { |
| | | height: 100%; |
| | | background: #F5F7FA; |
| | | |
| | | .form-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(3, 1fr); |
| | | gap: 24px; |
| | | margin-bottom: 24px; |
| | | |
| | | @media screen and (max-width: 1200px) { |
| | | grid-template-columns: repeat(2, 1fr); |
| | | .form-card { |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | |
| | | .header-title { |
| | | margin-bottom: 24px; |
| | | |
| | | &-left { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | img { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | @media screen and (max-width: 768px) { |
| | | grid-template-columns: 1fr; |
| | | |
| | | div { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .end-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 10px; |
| | | |
| | | button { |
| | | width: 180px; |
| | | height: 36px; |
| | | // background: #409EFF; |
| | | } |
| | | } |
| | | |
| | | .strain-form { |
| | | padding: 0 40px; |
| | | |
| | | .form-row { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 24px; |
| | | margin-bottom: 24px; |
| | | |
| | | &.three-columns { |
| | | |
| | | .el-form-item, |
| | | .form-item-placeholder { |
| | | flex: 1; |
| | | min-width: 280px; |
| | | |
| | | @media screen and (max-width: 1200px) { |
| | | min-width: calc(50% - 12px); |
| | | } |
| | | |
| | | @media screen and (max-width: 768px) { |
| | | min-width: 100%; |
| | | } |
| | | } |
| | | |
| | | .form-item-placeholder { |
| | | @media screen and (max-width: 1200px) { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-form-item { |
| | | margin-bottom: 0; |
| | |
| | | } |
| | | } |
| | | |
| | | .batch-add-dialog { |
| | | :deep(.el-dialog__header) { |
| | | margin: 0; |
| | | padding: 20px; |
| | | text-align: center; |
| | | border-bottom: 1px solid #EBEEF5; |
| | | |
| | | .el-dialog__title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog__body) { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .dialog-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .batch-form { |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | :deep(.el-form-item) { |
| | | width: 320px; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | :deep(.el-form-item__label) { |
| | | width: 100%; |
| | | color: #606266; |
| | | font-weight: normal; |
| | | padding-bottom: 8px; |
| | | |
| | | &::before { |
| | | color: #F56C6C; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-input) { |
| | | width: 100%; |
| | | |
| | | input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .dialog-notice { |
| | | margin-top: 16px; |
| | | text-align: center; |
| | | |
| | | p { |
| | | margin: 0; |
| | | line-height: 22px; |
| | | color: #606266; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog__footer) { |
| | | padding: 0 20px 20px; |
| | | text-align: center; |
| | | |
| | | .el-button { |
| | | width: 180px; |
| | | height: 36px; |
| | | padding: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 14px; |
| | | border-radius: 4px; |
| | | margin: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .end-btn { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | margin: 0; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |