<template>
|
<Card>
|
<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="projectId">
|
<el-select
|
v-model="form.projectId"
|
placeholder="请选择项目组"
|
:key="teamList.length"
|
filterable
|
clearable
|
:loading="teamLoading"
|
@focus="fetchTeamList"
|
>
|
<el-option
|
v-for="item in teamList"
|
:key="item.id"
|
:label="item.teamName"
|
:value="item.id"
|
/>
|
</el-select>
|
</el-form-item>
|
|
<!-- 修改菌种编号为单行显示 -->
|
<el-form-item label="菌种编号" prop="strainCode" class="strain-code-form-item">
|
<div class="strain-code-wrapper">
|
<el-input
|
v-model="form.strainCode"
|
placeholder="请输入前缀"
|
class="strain-code-input"
|
/>
|
<span class="strain-code-separator">-</span>
|
<el-input
|
:value="displayStrainSeq"
|
placeholder="序号"
|
class="strain-seq-input"
|
maxlength="3"
|
@input="handleSeqInput"
|
@blur="formatSeq"
|
@focus="handleFocus"
|
/>
|
</div>
|
</el-form-item>
|
|
<el-form-item label="菌种名称" prop="strainName">
|
<el-input v-model="form.strainName" placeholder="请输入"></el-input>
|
</el-form-item>
|
<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" class="full-width">
|
<el-input type="textarea" v-model="form.appraisalMethod" :rows="4" 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.remark" :rows="4" placeholder="请输入"></el-input>
|
</el-form-item>
|
</div>
|
|
<div class="end-btn" style="margin-top: 38px">
|
<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" />
|
</Card>
|
</template>
|
|
<script>
|
import SignatureCanvas from '@/components/SignatureCanvas.vue'
|
import {add, addBatch, edit, getDetail} from './service'
|
import {myTeamPageList} from "@/components/chooseProject/servce";
|
|
export default {
|
name: 'StrainLibraryManageAdd',
|
components: {
|
SignatureCanvas
|
},
|
data() {
|
return {
|
teamList: [],
|
teamLoading: false,
|
batchAddDialogVisible: false,
|
signatureVisible: false,
|
currentAction: '',
|
batchForm: {
|
count: ''
|
},
|
displayStrainSeq: '', // 显示用的序号(可能包含前导零)
|
cacheForm: null,
|
form: {
|
projectId: '',
|
strainCode: '',
|
strainName: '',
|
strainSeq: '',
|
source: '',
|
appraisalMethod: '',
|
characteristics: '',
|
storageLocation: '',
|
preservationMethod: '',
|
remark: ''
|
},
|
rules: {
|
projectId: [{required: true, message: '请选择所属项目组', trigger: 'change'}],
|
strainCode: [{
|
required: true,
|
validator: (rule, value, callback) => {
|
if (this.currentAction === 'submit' && !value) {
|
callback(new Error('请输入菌种编号前缀'));
|
} else {
|
callback();
|
}
|
},
|
trigger: 'change'
|
}],
|
displayStrainSeq: [{
|
validator: (rule, value, callback) => {
|
if (this.currentAction === 'submit') {
|
if (!value) {
|
callback(new Error('请输入序号'));
|
} else if (!/^\d{1,3}$/.test(value)) {
|
callback(new Error('请输入1-3位数字'));
|
} else {
|
callback();
|
}
|
} else {
|
callback();
|
}
|
},
|
trigger: 'blur'
|
}],
|
strainName: [{ 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' }]
|
}
|
}
|
},
|
deactivated() {
|
this.cacheForm = JSON.parse(JSON.stringify(this.form));
|
this.cacheForm.displayStrainSeq = this.displayStrainSeq
|
},
|
async activated() {
|
console.log('mounted')
|
await this.fetchTeamList();
|
|
this.form = {
|
strainCode: '',
|
strainName: '',
|
source: '',
|
strainSeq: '',
|
appraisalMethod: '',
|
characteristics: '',
|
storageLocation: '',
|
preservationMethod: '',
|
remark: ''
|
}
|
|
console.log('this.cacheForm', this.cacheForm)
|
if (this.cacheForm) {
|
this.form = this.cacheForm;
|
if (this.cacheForm.displayStrainSeq) {
|
this.displayStrainSeq = this.cacheForm.displayStrainSeq;
|
}
|
return
|
}
|
|
console.log('this.$route.query.id', this.$route.query.id)
|
if (this.$route.query.id && !this.cacheForm) {
|
const res = await getDetail({id: this.$route.query.id});
|
this.form = {...res}
|
|
console.log('projectId =', this.form.projectId, typeof this.form.projectId)
|
|
if (res.strainCode) {
|
const parts = res.strainCode.split('-');
|
if (parts.length > 1) {
|
const seq = parts.pop();
|
this.displayStrainSeq = seq.replace(/^0+/, '');
|
this.form.strainCode = parts.join('-');
|
} else {
|
this.form.strainCode = res.strainCode;
|
}
|
}
|
|
this.$forceUpdate();
|
}
|
},
|
watch: {
|
'$route.query.id'() {
|
this.form = {
|
strainCode: '',
|
strainName: '',
|
source: '',
|
appraisalMethod: '',
|
characteristics: '',
|
storageLocation: '',
|
preservationMethod: '',
|
remark: ''
|
}
|
this.displayStrainSeq = ''
|
}
|
},
|
methods: {
|
// 处理输入:只允许数字
|
handleSeqInput(value) {
|
console.log('输入值:', value);
|
|
// 如果是空字符串,清空所有
|
if (value === '') {
|
this.form.strainSeq = '';
|
this.displayStrainSeq = '';
|
return;
|
}
|
|
// 只保留数字,限制3位
|
let numStr = value.replace(/\D/g, '').slice(0, 3);
|
|
if (numStr) {
|
const num = parseInt(numStr);
|
if (!isNaN(num) && num >= 0 && num <= 999) {
|
// 存储时去除前导零
|
this.form.strainSeq = String(num);
|
// 显示时保留用户输入的内容(不补零,让用户看到自己输入的内容)
|
this.displayStrainSeq = numStr;
|
}
|
} else {
|
this.form.strainSeq = '';
|
this.displayStrainSeq = '';
|
}
|
|
console.log('存储值:', this.form.strainSeq);
|
console.log('显示值:', this.displayStrainSeq);
|
},
|
|
// 失去焦点时:补零到3位
|
formatSeq() {
|
console.log('失去焦点, 当前值:', this.form.strainSeq);
|
|
if (this.form.strainSeq) {
|
const num = parseInt(this.form.strainSeq);
|
if (!isNaN(num) && num >= 0 && num <= 999) {
|
// 保持存储值为数字字符串
|
this.form.strainSeq = String(num);
|
// 显示时补零到3位
|
this.displayStrainSeq = String(num).padStart(3, '0');
|
}
|
}
|
|
console.log('格式化后存储值:', this.form.strainSeq);
|
console.log('格式化后显示值:', this.displayStrainSeq);
|
},
|
|
// 获取焦点时:显示原始数字(去除前导零,便于编辑)
|
handleFocus() {
|
console.log('获取焦点, 当前值:', this.form.strainSeq);
|
|
if (this.form.strainSeq) {
|
// 显示原始数字,去除前导零
|
this.displayStrainSeq = this.form.strainSeq;
|
}
|
},
|
getFullStrainCode() {
|
const prefix = this.form.strainCode || '';
|
const seq = this.displayStrainSeq || '';
|
if (prefix && seq) {
|
const paddedSeq = String(seq).padStart(3, '0');
|
return `${prefix}-${paddedSeq}`;
|
}
|
return prefix;
|
},
|
async fetchTeamList() {
|
if (this.teamList.length > 0) return
|
this.teamLoading = true
|
try {
|
const res = await myTeamPageList()
|
this.teamList = res.data || res || []
|
|
console.log('this.teamList[0]: ',this.teamList[0])
|
} catch (error) {
|
console.error('获取项目组列表失败:', error)
|
this.$message.error('获取项目组列表失败')
|
} finally {
|
this.teamLoading = false
|
}
|
},
|
handleSubmit(isDraft) {
|
this.currentAction = 'submit'
|
|
// 手动验证序号
|
if (!this.displayStrainSeq || this.displayStrainSeq === '') {
|
this.$message.warning('请输入序号');
|
return;
|
}
|
|
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
|
}
|
})
|
},
|
async handleSignatureConfirm(signatureImage) {
|
const fullStrainCode = this.getFullStrainCode();
|
let requestData = {
|
projectId: this.form.projectId,
|
strainCode: fullStrainCode,
|
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: 1,
|
};
|
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.cacheForm = null
|
this.displayStrainSeq = null
|
this.signatureVisible = false;
|
this.$closeCurrentView('/strain-library/strain-library-manage');
|
this.$message.success('操作成功');
|
} catch (error) {
|
this.$message.error('操作失败');
|
}
|
}
|
}
|
}
|
</script>
|
|
<style scoped lang="less">
|
.add-strain {
|
height: 100%;
|
background: #F5F7FA;
|
|
.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;
|
}
|
|
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;
|
}
|
}
|
|
.strain-form {
|
padding: 0 40px;
|
|
// 菌种编号表单项样式
|
.strain-code-form-item {
|
// 关键:让表单项占满宽度
|
flex: 1;
|
min-width: 280px;
|
|
:deep(.el-form-item__content) {
|
display: flex;
|
align-items: center;
|
width: 100%;
|
line-height: 36px;
|
}
|
}
|
|
.strain-code-wrapper {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
width: 100%;
|
flex: 1;
|
|
.strain-code-input {
|
flex: 1; // 改为 flex:1 自适应
|
min-width: 0; // 防止溢出
|
|
:deep(.el-input__inner) {
|
height: 36px;
|
line-height: 36px;
|
border-radius: 4px;
|
width: 100%;
|
}
|
}
|
|
.strain-code-separator {
|
color: #909399;
|
font-size: 16px;
|
font-weight: bold;
|
user-select: none;
|
flex-shrink: 0;
|
line-height: 36px;
|
padding: 0 2px;
|
}
|
|
.strain-seq-input {
|
width: 90px; // 固定宽度
|
flex-shrink: 0; // 不被压缩
|
|
:deep(.el-input__inner) {
|
height: 36px;
|
line-height: 36px;
|
text-align: center;
|
padding: 0 5px;
|
border-radius: 4px;
|
width: 100%;
|
|
&::-webkit-inner-spin-button,
|
&::-webkit-outer-spin-button {
|
-webkit-appearance: none;
|
margin: 0;
|
}
|
-moz-appearance: textfield;
|
}
|
}
|
}
|
|
.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;
|
|
&.full-width {
|
width: 100%;
|
}
|
}
|
}
|
|
:deep(.el-form-item__label) {
|
font-weight: normal;
|
color: #606266;
|
padding-bottom: 8px;
|
line-height: 20px;
|
}
|
|
:deep(.el-form-item__content) {
|
line-height: unset;
|
}
|
|
:deep(.el-input__inner) {
|
border-radius: 4px;
|
height: 36px;
|
line-height: 36px;
|
}
|
|
:deep(.el-textarea__inner) {
|
border-radius: 4px;
|
padding: 8px 12px;
|
min-height: 120px;
|
}
|
}
|
|
.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;
|
justify-content: center;
|
gap: 10px;
|
|
:deep(.el-button) {
|
width: 180px;
|
height: 36px;
|
padding: 0;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-size: 14px;
|
border-radius: 4px;
|
margin: 0;
|
}
|
}
|
</style>
|